인그레스 기능
: HTTP(서비스) 부하분산 , 카나리 업그레이드인그레스 컨트롤러
: 인그레스의 실제 동작 구현은 인그레스 컨트롤러(Nginx, Kong 등)가 담당인그레스 + 인그레스 컨트롤러(Nginx) 기능
: HTTP(서비스) 부하분산 , 카나리 업그레이드 , HTTPS 처리(TLS 종료)apiVersion: apps/v1
kind: Deployment
metadata:
name: deploy1-websrv
spec:
replicas: 1
selector:
matchLabels:
app: websrv
template:
metadata:
labels:
app: websrv
spec:
containers:
- name: pod-web
image: nginx
---
apiVersion: v1
kind: Service
metadata:
name: svc1-web
spec:
ports:
- name: web-port
port: 9001
targetPort: 80
selector:
app: websrv
type: **ClusterIP**
apiVersion: apps/v1
kind: Deployment
metadata:
name: deploy2-guestsrv
spec:
replicas: 2
selector:
matchLabels:
app: guestsrv
template:
metadata:
labels:
app: guestsrv
spec:
containers:
- name: pod-guest
image: gcr.io/google-samples/kubernetes-bootcamp:v1
ports:
- containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
name: svc2-guest
spec:
ports:
- name: guest-port
port: 9002
targetPort: 8080
selector:
app: guestsrv
type: **NodePort**
apiVersion: apps/v1
kind: Deployment
metadata:
name: deploy3-adminsrv
spec:
replicas: 3
selector:
matchLabels:
app: adminsrv
template:
metadata:
labels:
app: adminsrv
spec:
containers:
- name: pod-admin
image: k8s.gcr.io/echoserver:1.5
ports:
- containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
name: svc3-admin
spec:
ports:
- name: admin-port
port: 9003
targetPort: 8080
selector:
app: adminsrv
# kubectl apply -f svc1-pod.yaml
deployment.apps/deploy1-websrv created
service/svc1-web created
# kubectl apply -f svc2-pod.yaml
deployment.apps/deploy2-guestsrv created
service/svc2-guest created
# kubectl apply -f svc3-pod.yaml
deployment.apps/deploy3-adminsrv created
service/svc3-admin created
watch -d 'kubectl get pods,svc,ep -o wide'
Every 2.0s: kubectl get pods,svc,ep -o wide master: Sun Jul 18 06:24:24 2021
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod/deploy1-websrv-574449b8df-mzxmg 1/1 Running 0 46s 172.16.235.140 worker1 <none> <none>
pod/deploy2-guestsrv-6f7f766988-9hxjw 1/1 Running 0 41s 172.16.189.105 worker2 <none> <none>
pod/deploy2-guestsrv-6f7f766988-q9r4j 1/1 Running 0 41s 172.16.235.141 worker1 <none> <none>
pod/deploy3-adminsrv-7bd5d589b9-drllf 1/1 Running 0 39s 172.16.189.106 worker2 <none> <none>
pod/deploy3-adminsrv-7bd5d589b9-snjvg 1/1 Running 0 39s 172.16.182.43 worker3 <none> <none>
pod/deploy3-adminsrv-7bd5d589b9-vl9lh 1/1 Running 0 39s 172.16.235.142 worker1 <none> <none>
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 4m51s <none>
service/svc1-web ClusterIP 10.99.16.110 <none> 9001/TCP 46s app=websrv
service/svc2-guest NodePort 10.111.55.249 <none> 9002:30371/TCP 41s app=guestsrv
service/svc3-admin ClusterIP 10.99.94.161 <none> 9003/TCP 39s app=adminsrv
NAME ENDPOINTS AGE
endpoints/kubernetes 192.168.1.211:6443 4m51s
endpoints/svc1-web 172.16.235.140:80 46s
endpoints/svc2-guest 172.16.189.105:8080,172.16.235.141:8080 41s
endpoints/svc3-admin 172.16.182.43:8080,172.16.189.106:8080,172.16.235.142:8080 39s
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-1
annotations:
kubernetes.io/ingress.class: "nginx"
#nginx.ingress.kubernetes.io/upstream-hash-by: "true"
spec:
rules:
- http:
paths:
- path: /
backend:
serviceName: svc1-web
servicePort: 80
- path: /guest
backend:
serviceName: svc2-guest
servicePort: 8080
- path: /admin
backend:
serviceName: svc3-admin
servicePort: 8080
# kubectl apply -f ingress1.yaml
ingress.networking.k8s.io/ingress-1 created
# k get ing
NAME CLASS HOSTS ADDRESS PORTS AGE
ingress-1 <none> * 80 14s
watch -d 'kubectl get ing,svc,ep -o wide'
Every 2.0s: kubectl get ing,svc,ep -o wide master: Sun Jul 18 06:30:06 2021
NAME CLASS HOSTS ADDRESS PORTS AGE
**ingress.networking.k8s.io/ingress-1 <none> * 192.168.1.211 80 67s**
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 10m <none>
service/svc1-web ClusterIP 10.99.16.110 <none> 9001/TCP 6m28s app=websrv
service/svc2-guest NodePort 10.111.55.249 <none> 9002:30371/TCP 6m23s app=guestsrv
service/svc3-admin ClusterIP 10.99.94.161 <none> 9003/TCP 6m21s app=adminsrv
NAME ENDPOINTS AGE
endpoints/kubernetes 192.168.1.211:6443 10m
endpoints/svc1-web 172.16.235.140:80 6m28s
endpoints/svc2-guest 172.16.189.105:8080,172.16.235.141:8080 6m23s
endpoints/svc3-admin 172.16.182.43:8080,172.16.189.106:8080,172.16.235.142:8080 6m21s
간편한 테스트를 위해 NodePort 타입(externalTrafficPolicy: Local) 로 마스터 노드에 생성한다.
양이 길어 다운로드 받아 활용
# curl -s -o nginx-ingress.yaml -O -L curl -s -O https://raw.githubusercontent.com/gasida/DKOS/main/6/nginx-ingress.yaml
# sed -i 's/**k8s-m**/master/g' nginx-ingress.yaml
# kubectl apply -f nginx-ingress.yaml
namespace/ingress-nginx unchanged
serviceaccount/ingress-nginx unchanged
configmap/ingress-nginx-controller configured
clusterrole.rbac.authorization.k8s.io/ingress-nginx unchanged
clusterrolebinding.rbac.authorization.k8s.io/ingress-nginx unchanged
role.rbac.authorization.k8s.io/ingress-nginx unchanged
rolebinding.rbac.authorization.k8s.io/ingress-nginx unchanged
service/ingress-nginx-controller-admission unchanged
service/ingress-nginx-controller unchanged
deployment.apps/ingress-nginx-controller configured
validatingwebhookconfiguration.admissionregistration.k8s.io/ingress-nginx-admission configured
serviceaccount/ingress-nginx-admission unchanged
clusterrole.rbac.authorization.k8s.io/ingress-nginx-admission unchanged
clusterrolebinding.rbac.authorization.k8s.io/ingress-nginx-admission unchanged
role.rbac.authorization.k8s.io/ingress-nginx-admission unchanged
rolebinding.rbac.authorization.k8s.io/ingress-nginx-admission unchanged
job.batch/ingress-nginx-admission-create unchanged
job.batch/ingress-nginx-admission-patch unchanged
# kubectl get svc -n ingress-nginx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
ingress-nginx-controller NodePort 10.102.103.48 <none> 80:32182/TCP,443:31768/TCP 6d18h
ingress-nginx-controller-admission ClusterIP 10.110.11.197 <none> 443/TCP
# kubectl describe svc -n ingress-nginx ingress-nginx-controller | grep Local
External Traffic Policy: Local
# export IngHttp=$(kubectl get service -n ingress-nginx ingress-nginx-controller -o jsonpath='{.spec.ports[0].nodePort}')
# echo $IngHttp
32182
# export IngHttps=$(kubectl get service -n ingress-nginx ingress-nginx-controller -o jsonpath='{.spec.ports[1].nodePort}')
# echo $IngHttps
31768
# watch -d 'kubectl get pod -n ingress-nginx -o wide -l app.kubernetes.io/component=controller; echo; kubectl get svc -n ingress-nginx; echo; kubectl get ingress,ep;'
Every 2.0s: kubectl get pod -n ingress-nginx -o wide -l app.kubernetes.io/component=controller; echo; kubectl get svc -n ingress-nginx; echo; ku... master: Sun Jul 18 06:46:21 2021
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
ingress-nginx-controller-566455f794-w7bnc 1/1 Running 2 6d18h 172.16.219.69 master <none> <none>
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
**ingress-nginx-controller NodePort 10.102.103.48 <none> 80:32182/TCP,443:31768/TCP 6d18h**
ingress-nginx-controller-admission ClusterIP 10.110.11.197 <none> 443/TCP 6d18h
NAME CLASS HOSTS ADDRESS PORTS AGE
ingress.networking.k8s.io/ingress-1 <none> * 192.168.1.211 80 17m
NAME ENDPOINTS AGE
endpoints/kubernetes 192.168.1.211:6443 26m
endpoints/svc1-web 172.16.235.140:80 22m
endpoints/svc2-guest 172.16.189.105:8080,172.16.235.141:8080 22m
endpoints/svc3-admin 172.16.182.43:8080,172.16.189.106:8080,172.16.235.142:8080 22m
# MASTER=192.168.1.211
# curl $MASTER:$IngHttp
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
... 생략 ...
# for i in {1..100}; do curl -s $MASTER:$IngHttp/guest ; done | sort | uniq -c | sort -nr
50 Hello Kubernetes bootcamp! | Running on: deploy2-guestsrv-6f7f766988-q9r4j | v=1
50 Hello Kubernetes bootcamp! | Running on: deploy2-guestsrv-6f7f766988-9hxjw | v=1
# for i in {1..100}; do curl -s $MASTER:$IngHttp/admin | grep Hostname ; done | sort | uniq -c | sort -nr
34 Hostname: deploy3-adminsrv-7bd5d589b9-snjvg
33 Hostname: deploy3-adminsrv-7bd5d589b9-vl9lh
33 Hostname: deploy3-adminsrv-7bd5d589b9-drllf
# kubectl delete deployments,svc,ingress --all
deployment.apps "deploy1-websrv" deleted
deployment.apps "deploy2-guestsrv" deleted
deployment.apps "deploy3-adminsrv" deleted
service "kubernetes" deleted
service "svc1-web" deleted
service "svc2-guest" deleted
service "svc3-admin" deleted
ingress.networking.k8s.io "ingress-1" deleted
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: ingress-2
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /dkos
kubernetes.io/ingress.class: "nginx"
spec:
rules:
- host: **aiden.com**
http:
paths:
- path: /
backend:
serviceName: svc3-admin
servicePort: 8080
- host: "***.aiden.com**"
http:
paths:
- path: /echo
backend:
serviceName: svc3-admin
servicePort: 8080
# kubectl apply -f ingress2.yaml
ingress.networking.k8s.io/ingress-2 created
# kubectl apply -f svc3-pod.yaml
deployment.apps/deploy3-adminsrv created
service/svc3-admin created
# kubectl get ingress
NAME CLASS HOSTS ADDRESS PORTS AGE
ingress-2 <none> aiden,*.aiden 192.168.1.211 80 71s
# kubectl describe ingress ingress-2
Name: ingress-2
Namespace: default
Address: 192.168.1.211
Default backend: default-http-backend:80 (<error: endpoints "default-http-backend" not found>)
Rules:
Host Path Backends
---- ---- --------
aiden
/ svc3-admin:8080 ()
*.aiden
/echo svc3-admin:8080 ()
Annotations: kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/rewrite-target: /dkos
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Sync 74s (x2 over 105s) nginx-ingress-controller Scheduled for sync
MASTER=192.168.1.211
MYDOMAIN1=aiden.com
MYDOMAIN2=test.aiden.com
cat << EOF >> /etc/hosts
$MASTER $MYDOMAIN1
$MASTER $MYDOMAIN2
EOF
# curl $MYDOMAIN1:$IngHttp
Hostname: deploy3-adminsrv-7bd5d589b9-ppwbc
Pod Information:
-no pod information available-
Server values:
server_version=nginx: 1.13.0 - lua: 10008
Request Information:
client_address=172.16.219.69
method=GET
... 생략 ...
# kubectl delete deployments,svc,ingress --all
deployment.apps "deploy3-adminsrv" deleted
service "kubernetes" deleted
service "svc3-admin" deleted
ingress.networking.k8s.io "ingress-2" deleted
apiVersion: apps/v1
kind: Deployment
metadata:
name: dp-v1
spec:
replicas: 3
selector:
matchLabels:
app: svc-v1
template:
metadata:
labels:
app: svc-v1
spec:
containers:
- name: pod-v1
image: k8s.gcr.io/echoserver:1.5
ports:
- containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
name: svc-v1
spec:
ports:
- name: web-port
port: 9001
targetPort: 8080
selector:
app: svc-v1
apiVersion: apps/v1
kind: Deployment
metadata:
name: dp-v2
spec:
replicas: 3
selector:
matchLabels:
app: svc-v2
template:
metadata:
labels:
app: svc-v2
spec:
containers:
- name: pod-v2
image: k8s.gcr.io/echoserver:1.6
ports:
- containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
name: svc-v2
spec:
ports:
- name: web-port
port: 9001
targetPort: 8080
selector:
app: svc-v2
# kubectl apply -f canary-svc1-pod.yaml
deployment.apps/dp-v1 created
service/svc-v1 created
# kubectl apply -f canary-svc2-pod.yaml
deployment.apps/dp-v2 created
service/svc-v2 created
# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 3m57s
svc-v1 ClusterIP 10.105.182.84 <none> 9001/TCP 44s
svc-v2 ClusterIP 10.97.254.145 <none> 9001/TCP 41s
# for pod in $(kubectl get pod -o wide -l app=svc-v1 |awk 'NR>1 {print $6}'); do curl -s $pod:8080 | egrep '(Hostname|nginx)'; done
Hostname: dp-v1-cdd8dc687-2cbk4
server_version=nginx: 1.13.0 - lua: 10008
Hostname: dp-v1-cdd8dc687-6mnzh
server_version=nginx: 1.13.0 - lua: 10008
Hostname: dp-v1-cdd8dc687-jsmnh
server_version=nginx: 1.13.0 - lua: 10008
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: ingress-canary-v1
annotations:
kubernetes.io/ingress.class: "nginx"
spec:
rules:
- host: aiden.com
http:
paths:
- backend:
serviceName: svc-v1
servicePort: 8080
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: ingress-canary-v2
annotations:
kubernetes.io/ingress.class: "nginx"
**nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-weight: "10"**
spec:
rules:
- host: aiden.com
http:
paths:
- backend:
serviceName: svc-v2
servicePort: 8080
# for i in {1..100}; do curl -s $MYDOMAIN1:$IngHttp | grep nginx ; done | sort | uniq -c | sort -nr
90 server_version=nginx: 1.13.0 - lua: 10008
10 server_version=nginx: 1.13.1 - lua: 10008
# for i in {1..100}; do curl -s $MYDOMAIN1:$IngHttp | grep nginx ; done | sort | uniq -c | sort -nr
84 server_version=nginx: 1.13.0 - lua: 10008
16 server_version=nginx: 1.13.1 - lua: 10008
약 90:10 비율로 로드밸런싱 된다.
# kubectl get ingress ingress-canary-v2 -o yaml | sed -e "s/weight: \"10\"/weight: \"50\"/" | kubectl apply -f -
ingress.networking.k8s.io/ingress-canary-v2 configured
# for i in {1..100}; do curl -s $MYDOMAIN1:$IngHttp | grep nginx ; done | sort | uniq -c | sort -nr
50 server_version=nginx: 1.13.1 - lua: 10008
50 server_version=nginx: 1.13.0 - lua: 10008
# for i in {1..100}; do curl -s $MYDOMAIN1:$IngHttp | grep nginx ; done | sort | uniq -c | sort -nr
55 server_version=nginx: 1.13.1 - lua: 10008
45 server_version=nginx: 1.13.0 - lua: 10008
weight를 10→50으로 변경 후 약 50:50 비율로 로드밸런싱 되었다.
# kubectl delete deployments,svc,ingress --all
deployment.apps "dp-v1" deleted
deployment.apps "dp-v2" deleted
service "kubernetes" deleted
service "svc-v1" deleted
service "svc-v2" deleted
ingress.networking.k8s.io "ingress-canary-v1" deleted
ingress.networking.k8s.io "ingress-canary-v2" deleted
apiVersion: v1
kind: Pod
metadata:
name: pod-https
labels:
app: https
spec:
containers:
- name: container
image: k8s.gcr.io/echoserver:1.6
---
apiVersion: v1
kind: Service
metadata:
name: svc-https
spec:
selector:
app: https
ports:
- port: 8080
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: https
spec:
tls:
- hosts:
- aiden.com
secretName: secret-https
rules:
- host: aiden.com
http:
paths:
- backend:
serviceName: svc-https
servicePort: 8080
# kubectl apply -f svc-pod.yaml
pod/pod-https created
service/svc-https created
# kubectl apply -f ssl-termination-ingress.yaml
ingress.networking.k8s.io/https created
# mkdir key && cd key
# openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout tls.key -out tls.crt -subj "/CN=aiden.com/O=aiden.com"
Generating a RSA private key
.......................................+++++
...............................+++++
writing new private key to 'tls.key'
-----
# kubectl create secret tls secret-https --key tls.key --cert tls.crt
secret/secret-https created
# kubectl get secrets secret-https
NAME TYPE DATA AGE
secret-https kubernetes.io/tls 2 9s
# kubectl get secrets secret-https -o yaml
\apiVersion: v1
data:
... 생략 ...
# export IngHttps=$(kubectl get service -n ingress-nginx ingress-nginx-controller -o jsonpath='{.spec.ports[1].nodePort}')
# echo $IngHttps
31768
# curl -k https://$MYDOMAIN1:$IngHttps
Hostname: pod-https
Pod Information:
-no pod information available-
Server values:
server_version=nginx: 1.13.1 - lua: 10008
Request Information:
client_address=172.16.219.69
... 생략 ...
# kubectl delete -f nginx-ingress.yaml
# kubectl delete pod,svc,ingress --all
pod "pod-https" deleted
service "kubernetes" deleted
service "svc-https" deleted
ingress.networking.k8s.io "https" deleted