보통은 알려진 CA에서 발급한 TLS 인증서를 사용하여 레지스트리를 보호하는 것이 매우 권장되지만, 자체 서명된 인증서를 사용하거나 암호화되지 않은 HTTP 연결을 통해 레지스트리를 사용하도록 선택할 수 있습니다. 만약 인터넷이 안되거나 그냥 개인이 따로 저장하겠다고하면 HTTP 연결을 통해 개인 저장소를 구축할 수 있습니다.
# docker run -d -p 5000:5000 --name hello-registry \
> -v /tmp/registry:/tmp/registry \
> registry
2976da0da8d746a1ba60f88930dd46bff8143795c516dd9653fcf1a6942432e5
#
# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2976da0da8d7 registry "/entrypoint.sh /etc…" 3 seconds ago Up 2 seconds 0.0.0.0:5000->5000/tcp, :::5000->5000/tcp hello-registry
이미지 파일은 호스트의 /tmp/registry 디렉터리에 저장됩니다.
이미지 tag, push 설정하기
# docker build --tag hello:0.1 .
# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hello 0.1 75f0625417ad 36 seconds ago 232MB
# docker tag hello:0.1 localhost:5000/hello:0.1
# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hello 0.1 75f0625417ad About a minute ago 232MB
localhost:5000/hello 0.1 75f0625417ad About a minute ago 232MB
# docker push localhost:5000/hello:0.1
The push refers to repository [localhost:5000/hello]
2d1630f34efb: Pushed
0492b535da40: Pushed
1db69eba3ab3: Pushed
b9b64cd744c9: Pushed
83109fa660b2: Pushed
30d3c4334a23: Pushed
f2fa9f4cf8fd: Pushed
0.1: digest: sha256:6b8296113e568e6184eb893fd02f006034c26b0778c86922cd65554f0f379106 size: 1782
가지고있는 Dockerfile을 build 하여 name : hello | tag : 0.1로 image 생성
tag 생성 : docker tag <이미지이름>:<tag> <registry URL>/<이미지 이름>:<tag>
push 명령 : docker push <registry URL>/<이미지 이름>:<tag>
개인저장소에 있는 이미지를 Pull 받을 서버
# docker pull 192.168.0.201:5000/hello:0.1
Error response from daemon: Get "https://192.168.0.201:5000/v2/": http: server gave HTTP response to HTTPS client
pull 명령으로 개인저장소 서버에서 이미지를 받아오는데 오류 로그 발생
해결방법 : insecure-registries 설정 필요
# vi /etc/docker/daemon.json
{
"insecure-registries" : ["192.168.0.201:5000"]
}
# docker pull 192.168.0.201:5000/hello:0.1
0.1: Pulling from hello
2e6e20c8e2e6: Pull complete
0551a797c01d: Pull complete
512123a864da: Pull complete
0cde67eab025: Pull complete
119857f951bc: Pull complete
41786f85cd57: Pull complete
56705ad25a7d: Pull complete
Digest: sha256:6b8296113e568e6184eb893fd02f006034c26b0778c86922cd65554f0f379106
Status: Downloaded newer image for 192.168.0.201:5000/hello:0.1
192.168.0.201:5000/hello:0.1
# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
192.168.0.201:5000/hello 0.1 75f0625417ad 14 minutes ago 232MB
# docker login
Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one.
Username: djwlstn12345
Password:
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store
Login Succeeded
만약 위 방법으로 안된다면 docker logout 후 다시 login 해보시길 바랍니다.
시크릿은 암호, 토큰 또는 키와 같은 소량의 중요한 데이터를 포함하는 오브젝트이다. 이를 사용하지 않으면 중요한 정보가 파드 명세나 컨테이너 이미지에 포함될 수 있다. 시크릿을 사용한다는 것은 사용자의 기밀 데이터를 애플리케이션 코드에 넣을 필요가 없음을 뜻한다.
시크릿은 시크릿을 사용하는 파드와 독립적으로 생성될 수 있기 때문에, 파드를 생성하고, 확인하고, 수정하는 워크플로우 동안 시크릿(그리고 데이터)이 노출되는 것에 대한 위험을 경감시킬 수 있다. 쿠버네티스 및 클러스터에서 실행되는 애플리케이션은 비밀 데이터를 비휘발성 저장소에 쓰는 것을 피하는 것과 같이, 시크릿에 대해 추가 예방 조치를 취할 수도 있다.
시크릿은 컨피그맵과 유사하지만 특별히 기밀 데이터를 보관하기 위한 것이다.
주의
쿠버네티스 시크릿은 기본적으로 API 서버의 기본 데이터 저장소(etcd)에 암호화되지 않은 상태로 저장된다. API 접근(access) 권한이 있는 모든 사용자 또는 etcd에 접근할 수 있는 모든 사용자는 시크릿을 조회하거나 수정할 수 있다. 또한 네임스페이스에서 파드를 생성할 권한이 있는 사람은 누구나 해당 접근을 사용하여 해당 네임스페이스의 모든 시크릿을 읽을 수 있다. 여기에는 디플로이먼트 생성 기능과 같은 간접 접근이 포함된다.
1. 시크릿을 안전하게 사용하려면 최소한 다음의 단계를 따르는 것이 좋다.
2. 시크릿에 대해 저장된 데이터 암호화(Encryption at Rest)를 활성화한다.시크릿 읽기 및 쓰기를 제한하는 RBAC 규칙을 활성화 또는 구성한다.
3. 파드 생성 권한을 가진 사람은 암묵적으로 시크릿에 접근할 수 있음에 주의한다.적절한 경우, RBAC과 같은 메커니즘을 사용하여 새로운 시크릿을 생성하거나 기존 시크릿을 대체할 수 있는 주체(principal)들을 제한한다.
시크릿의 사용
파드가 시크릿을 사용하는 주요한 방법으로 다음의 세 가지가 있다.
하나 이상의 컨테이너에 마운트된 볼륨 내의 파일로써 사용.
컨테이너 환경 변수로써 사용.
파드의 이미지를 가져올 때 kubelet에 의해 사용.
쿠버네티스 컨트롤 플레인 또한 시크릿을 사용한다. 예를 들어, 부트스트랩 토큰 시크릿은 노드 등록을 자동화하는 데 도움을 주는 메커니즘이다
Secret 사용
# secret 배포 YAML 파일 생성 (암호화 base64 지원)
jinsu@jinsu:~$ cat secret.yaml
apiVersion: v1
kind: Secret
metadata:
name: mysecret
type: Opaque
data:
username: YWRtaW4=
password: MWYyZDFlMmU2N2Rm
jinsu@jinsu:~$
# secret 생성 및 확인
jinsu@jinsu:~$ kubectl apply -f secret.yaml
secret/mysecret created
jinsu@jinsu:~$
jinsu@jinsu:~$ kubectl get secret
NAME TYPE DATA AGE
default-token-vm2hl kubernetes.io/service-account-token 3 8h
mysecret Opaque 2 5s
jinsu@jinsu:~$
# secret 상세정보
jinsu@jinsu:~$ kubectl get secret mysecret -oyaml
apiVersion: v1
data:
password: MWYyZDFlMmU2N2Rm
username: YWRtaW4=
kind: Secret
metadata:
annotations:
kubectl.kubernetes.io/last-applied-configuration: |
{"apiVersion":"v1","data":{"password":"MWYyZDFlMmU2N2Rm","username":"YWRtaW4="},"kind":"Secret","metadata":{"annotations":{},"name":"mysecret","namespace":"default"},"type":"Opaque"}
creationTimestamp: "2022-08-14T09:37:57Z"
name: mysecret
namespace: default
resourceVersion: "19863"
selfLink: /api/v1/namespaces/default/secrets/mysecret
uid: 221983f8-81b7-4e62-bd7d-736b88dcdba8
type: Opaque
jinsu@jinsu:~$
# 같은 secret2를 생성 (암호화하지 않음)
jinsu@jinsu:~$ cat secret2.yaml
apiVersion: v1
kind: Secret
metadata:
name: mysecret2
type: Opaque
stringData:
username: admin
password: password
jinsu@jinsu:~$
# secret2 생성 및 확인
jinsu@jinsu:~$ kubectl apply -f secret2.yaml
secret/mysecret2 created
jinsu@jinsu:~$ kubectl get secret
NAME TYPE DATA AGE
default-token-vm2hl kubernetes.io/service-account-token 3 8h
mysecret Opaque 2 6m39s
mysecret2 Opaque 2 4s
jinsu@jinsu:~$
# secret2 상세정보를 보면 계정과 패스워드가 자동 암호화되는것을 볼 수 있다.
jinsu@jinsu:~$ kubectl get secret mysecret2 -oyaml
apiVersion: v1
data:
password: cGFzc3dvcmQ=
username: YWRtaW4=
kind: Secret
metadata:
annotations:
kubectl.kubernetes.io/last-applied-configuration: |
{"apiVersion":"v1","kind":"Secret","metadata":{"annotations":{},"name":"mysecret2","namespace":"default"},"stringData":{"password":"password","username":"admin"},"type":"Opaque"}
creationTimestamp: "2022-08-14T09:44:32Z"
name: mysecret2
namespace: default
resourceVersion: "20151"
selfLink: /api/v1/namespaces/default/secrets/mysecret2
uid: dec64c7d-f910-4e3d-8da3-0317118a5fa1
type: Opaque
jinsu@jinsu:~$
하나의 크론잡 오브젝트는 크론탭 (크론 테이블) 파일의 한 줄과 같다. 크론잡은 잡을 크론 형식으로 쓰여진 주어진 일정에 따라 주기적으로 동작시킨다.
주의 모든 크론잡 일정: 시간은 kube-controller-manager의 시간대를 기준으로 한다.
컨트롤 플레인이 파드 또는 베어 컨테이너에서 kube-controller-manager를 실행하는 경우, kube-controller-manager 컨테이너에 설정된 시간대는 크론잡 컨트롤러가 사용하는 시간대로 결정한다.
주의 v1 CronJob API은 위에서 설명한 타임존 설정을 공식적으로 지원하지는 않는다.
CRON_TZ 또는 TZ 와 같은 변수를 설정하는 것은 쿠버네티스 프로젝트에서 공식적으로 지원하지는 않는다. CRON_TZ 또는 TZ 와 같은 변수를 설정하는 것은 크론탭을 파싱하고 다음 잡 생성 시간을 계산하는 내부 라이브러리의 구현 상세사항이다. 프로덕션 클러스터에서는 사용을 권장하지 않는다. 크론잡 리소스에 대한 매니페스트를 생성할 때에는 제공하는 이름이 유효한 DNS 서브도메인 이름이어야 한다. 이름은 52자 이하여야 한다. 이는 크론잡 컨트롤러는 제공된 잡 이름에 11자를 자동으로 추가하고, 작업 이름의 최대 길이는 63자라는 제약 조건이 있기 때문이다.
크론잡
크론잡은 백업, 리포트 생성 등의 정기적 작업을 수행하기 위해 사용된다. 각 작업은 무기한 반복되도록 구성해야 한다(예: 1일/1주/1달마다 1회). 작업을 시작해야 하는 해당 간격 내 특정 시점을 정의할 수 있다.
동작 방식
CronJob -> Job 생성
CronJob 사용
# Cronjob 배포 YAML 파일 생성
jinsu@jinsu:~$ cat cronjob.yaml
apiVersion: batch/v1beta1
kind: CronJob
metadata:
name: hello
spec:
schedule: "* * * * *"
jobTemplate:
spec:
template:
spec:
containers:
- name: print-date
image: busybox
args: ["date"]
restartPolicy: OnFailure
jinsu@jinsu:~$
# Cronjob 생성 및 확인
jinsu@jinsu:~$ kubectl apply -f cronjob.yaml
cronjob.batch/hello created
jinsu@jinsu:~$ kubectl get cronjob
NAME SCHEDULE SUSPEND ACTIVE LAST SCHEDULE AGE
hello * * * * * False 0 <none> 17s
jinsu@jinsu:~$
# Cronjob으로 인한 job 생성 확인
jinsu@jinsu:~$ kubectl get job
NAME COMPLETIONS DURATION AGE
hello-1660469460 0/1 3s 3s
jinsu@jinsu:~$
jinsu@jinsu:~$ kubectl get job
NAME COMPLETIONS DURATION AGE
hello-1660469460 1/1 4s 74s
hello-1660469520 1/1 4s 14s
jinsu@jinsu:~$
jinsu@jinsu:~$ kubectl get job
NAME COMPLETIONS DURATION AGE
hello-1660469460 1/1 4s 2m45s
hello-1660469520 1/1 4s 105s
hello-1660469580 1/1 4s 45s
jinsu@jinsu:~$
CronJob 삭제
# CronJob 삭제
jinsu@jinsu:~$ kubectl delete cronjob hello
cronjob.batch "hello" deleted
jinsu@jinsu:~$
# 삭제확인
jinsu@jinsu:~$ kubectl get cronjob
No resources found in default namespace.
jinsu@jinsu:~$
jinsu@jinsu:~$ kubectl get job
No resources found in default namespace.
jinsu@jinsu:~$
# 현재 데몬셋 확인
jinsu@jinsu:~$ kubectl get daemonset
NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE
myapp 1 1 1 1 1 <none> 6m24s
# 데몬셋 삭제
jinsu@jinsu:~$ kubectl delete daemonset myapp
daemonset.apps "myapp" deleted
jinsu@jinsu:~$
jinsu@jinsu:~$ kubectl get daemonset
No resources found in default namespace.
jinsu@jinsu:~$ dd
디플로이먼트(Deployment) 는 파드와 레플리카셋(ReplicaSet)에 대한 선언적 업데이트를 제공한다.
디플로이먼트에서 의도하는 상태 를 설명하고, 디플로이먼트 컨트롤러(Controller)는 현재 상태에서 의도하는 상태로 비율을 조정하며 변경한다. 새 레플리카셋을 생성하는 디플로이먼트를 정의하거나 기존 디플로이먼트를 제거하고, 모든 리소스를 새 디플로이먼트에 적용할 수 있다.
Deployment -> Replicaset -> Pod
디플로이먼트 롤링 업데이트
디플로이먼트는 .spec.strategy.type==RollingUpdate 이면 파드를 롤링 업데이트 방식으로 업데이트 한다. maxUnavailable 와 maxSurge 를 명시해서 롤링 업데이트 프로세스를 제어할 수 있다.
최대 불가(Max Unavailable)
.spec.strategy.rollingUpdate.maxUnavailable 은 업데이트 프로세스 중에 사용할 수 없는 최대 파드의 수를 지정하는 선택적 필드이다. 이 값은 절대 숫자(예: 5) 또는 의도한 파드 비율(예: 10%)이 될 수 있다. 절대 값은 내림해서 백분율로 계산한다. 만약 .spec.strategy.rollingUpdate.maxSurge 가 0이면 값이 0이 될 수 없다. 기본 값은 25% 이다.
예를 들어 이 값을 30%로 설정하면 롤링업데이트 시작시 즉각 이전 레플리카셋의 크기를 의도한 파드 중 70%를 스케일 다운할 수 있다. 새 파드가 준비되면 기존 레플리카셋을 스케일 다운할 수 있으며, 업데이트 중에 항상 사용 가능한 전체 파드의 수는 의도한 파드의 수의 70% 이상이 되도록 새 레플리카셋을 스케일 업할 수 있다.
최대 서지(Max Surge)
.spec.strategy.rollingUpdate.maxSurge 는 의도한 파드의 수에 대해 생성할 수 있는 최대 파드의 수를 지정하는 선택적 필드이다. 이 값은 절대 숫자(예: 5) 또는 의도한 파드 비율(예: 10%)이 될 수 있다. MaxUnavailable 값이 0이면 이 값은 0이 될 수 없다. 절대 값은 올림해서 백분율로 계산한다. 기본 값은 25% 이다.
예를 들어 이 값을 30%로 설정하면 롤링업데이트 시작시 새 레플리카셋의 크기를 즉시 조정해서 기존 및 새 파드의 전체 갯수를 의도한 파드의 130%를 넘지 않도록 한다. 기존 파드가 죽으면 새로운 래플리카셋은 스케일 업할 수 있으며, 업데이트하는 동안 항상 실행하는 총 파드의 수는 최대 의도한 파드의 수의 130%가 되도록 보장한다
Deployment 설정
# deployment 생성 YAML을 작성
jinsu@jinsu:~$ cat deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: mynginx-deploy
spec:
replicas: 5
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 25%
maxSurge: 25%
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.7.9
jinsu@jinsu:~$
# deployment 생성
jinsu@jinsu:~$ kubectl apply -f deployment.yaml
deployment.apps/mynginx-deploy created
jinsu@jinsu:~$
# deployment 상태 및 pod 상태 확인
jinsu@jinsu:~$ kubectl get pod
NAME READY STATUS RESTARTS AGE
mynginx-deploy-55fbd9fd6d-jfm8k 0/1 ContainerCreating 0 15s
mynginx-deploy-55fbd9fd6d-f2pzv 0/1 ContainerCreating 0 15s
mynginx-deploy-55fbd9fd6d-kwf4k 0/1 ContainerCreating 0 15s
mynginx-deploy-55fbd9fd6d-dwljg 0/1 ContainerCreating 0 15s
mynginx-deploy-55fbd9fd6d-p75wx 1/1 Running 0 15s
jinsu@jinsu:~$ kubectl get deployment
NAME READY UP-TO-DATE AVAILABLE AGE
mynginx-deploy 1/5 5 1 17s
jinsu@jinsu:~$
# deployment 설정값 확인
jinsu@jinsu:~$ kubectl get deployment mynginx-deploy -oyaml
apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
deployment.kubernetes.io/revision: "1"
kubectl.kubernetes.io/last-applied-configuration: |
{"apiVersion":"apps/v1","kind":"Deployment","metadata":{"annotations":{},"name":"mynginx-deploy","namespace":"default"},"spec":{"replicas":5,"selector":{"matchLabels":{"app":"nginx"}},"strategy":{"rollingUpdate":{"maxSurge":"25%","maxUnavailable":"25%"},"type":"RollingUpdate"},"template":{"metadata":{"labels":{"app":"nginx"}},"spec":{"containers":[{"image":"nginx:1.7.9","name":"nginx"}]}}}}
creationTimestamp: "2022-08-14T08:24:38Z"
generation: 1
name: mynginx-deploy
namespace: default
resourceVersion: "16065"
selfLink: /apis/apps/v1/namespaces/default/deployments/mynginx-deploy
uid: 8262ede4-69af-499f-9f93-cba18f9b31c1
spec:
progressDeadlineSeconds: 600
replicas: 5
revisionHistoryLimit: 10
selector:
matchLabels:
app: nginx
strategy:
rollingUpdate:
maxSurge: 25%
maxUnavailable: 25%
type: RollingUpdate
template:
metadata:
creationTimestamp: null
labels:
app: nginx
spec:
containers:
- image: nginx:1.7.9
imagePullPolicy: IfNotPresent
name: nginx
resources: {}
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
dnsPolicy: ClusterFirst
restartPolicy: Always
schedulerName: default-scheduler
securityContext: {}
terminationGracePeriodSeconds: 30
status:
availableReplicas: 5
conditions:
- lastTransitionTime: "2022-08-14T08:25:02Z"
lastUpdateTime: "2022-08-14T08:25:02Z"
message: Deployment has minimum availability.
reason: MinimumReplicasAvailable
status: "True"
type: Available
- lastTransitionTime: "2022-08-14T08:24:38Z"
lastUpdateTime: "2022-08-14T08:25:06Z"
message: ReplicaSet "mynginx-deploy-55fbd9fd6d" has successfully progressed.
reason: NewReplicaSetAvailable
status: "True"
type: Progressing
observedGeneration: 1
readyReplicas: 5
replicas: 5
updatedReplicas: 5
jinsu@jinsu:~$
# deployment로 생성한 레플리카셋 확인
jinsu@jinsu:~$ kubectl get rs
NAME DESIRED CURRENT READY AGE
mynginx-deploy-55fbd9fd6d 5 5 5 5m44s
jinsu@jinsu:~$
deployment 배포시 image 에러가 발생
# 존재하지 않는 이미지로 이미지를 업데이트 하였을 때
jinsu@jinsu:~$ kubectl set image deployment mynginx-deploy nginx=nginx:1.9.30 --record
deployment.apps/mynginx-deploy image updated
jinsu@jinsu:~$
# deploy 하였을 때 maxUnavailabel을 25% 설정
jinsu@jinsu:~$ kubectl get deploy mynginx-deploy -oyaml
apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
deployment.kubernetes.io/revision: "3"
kubectl.kubernetes.io/last-applied-configuration: |
{"apiVersion":"apps/v1","kind":"Deployment","metadata":{"annotations":{},"name":"mynginx-deploy","namespace":"default"},"spec":{"replicas":5,"selector":{"matchLabels":{"app":"nginx"}},"strategy":{"rollingUpdate":{"maxSurge":"25%","maxUnavailable":"25%"},"type":"RollingUpdate"},"template":{"metadata":{"labels":{"app":"nginx"}},"spec":{"containers":[{"image":"nginx:1.7.9","name":"nginx"}]}}}}
kubernetes.io/change-cause: kubectl set image deployment mynginx-deploy nginx=nginx:1.9.30
--record=true
creationTimestamp: "2022-08-14T08:24:38Z"
generation: 3
name: mynginx-deploy
namespace: default
resourceVersion: "16969"
selfLink: /apis/apps/v1/namespaces/default/deployments/mynginx-deploy
uid: 8262ede4-69af-499f-9f93-cba18f9b31c1
spec:
progressDeadlineSeconds: 600
replicas: 5
revisionHistoryLimit: 10
selector:
matchLabels:
app: nginx
strategy:
rollingUpdate:
maxSurge: 25%
maxUnavailable: 25%
type: RollingUpdate
# pod에 에러가 발생하여도 전부 변경되지 않음
jinsu@jinsu:~$ kubectl get pod
NAME READY STATUS RESTARTS AGE
mynginx-deploy-7f9686c8fd-fbtxv 1/1 Running 0 9m20s
mynginx-deploy-7f9686c8fd-h7pms 1/1 Running 0 9m7s
mynginx-deploy-7f9686c8fd-4q92b 1/1 Running 0 9m5s
mynginx-deploy-7f9686c8fd-vq8lt 1/1 Running 0 9m20s
mynginx-deploy-69d67779d8-zq7bz 0/1 ErrImagePull 0 45s
mynginx-deploy-69d67779d8-lxkhm 0/1 ErrImagePull 0 45s
mynginx-deploy-69d67779d8-jhvcm 0/1 ErrImagePull 0 45s
jinsu@jinsu:~$
Deployment 명령어
# 이미지 변경
kubectl set image
jinsu@jinsu:~$ kubectl set image deployment mynginx-deploy nginx=nginx:1.9.1 --record
deployment.apps/mynginx-deploy image updated
jinsu@jinsu:~$
jinsu@jinsu:~$ kubectl get deploy
NAME READY UP-TO-DATE AVAILABLE AGE
mynginx-deploy 4/5 3 4 9m9s
jinsu@jinsu:~$
# 이미지가 변경된 것을 확인
jinsu@jinsu:~$ kubectl get pod mynginx-deploy-7f9686c8fd-vq8lt -oyaml | grep image
- image: nginx:1.9.1
imagePullPolicy: IfNotPresent
image: nginx:1.9.1
imageID: docker-pullable://nginx@sha256:2f68b99bc0d6d25d0c56876b924ec20418544ff28e1fb89a4c27679a40da811b
jinsu@jinsu:~$
# 업데이트 상태 확인
kubectl rollout status deployment mynginx-deploy
jinsu@jinsu:~$ kubectl rollout status deployment mynginx-deploy
deployment "mynginx-deploy" successfully rolled out
jinsu@jinsu:~$
# 업데이트 히스토리 확인
kubectl rollout history deployment mynginx-deploy
jinsu@jinsu:~$ kubectl rollout history deployment mynginx-deploy
deployment.apps/mynginx-deploy
REVISION CHANGE-CAUSE
1 <none>
2 kubectl set image deployment mynginx-deploy nginx=nginx:1.9.1 --record=true
jinsu@jinsu:~$
# deployment 세부정보 가져오기
jinsu@jinsu:~$ kubectl describe deployment mynginx-deploy
Name: mynginx-deploy
Namespace: default
CreationTimestamp: Sun, 14 Aug 2022 08:24:38 +0000
Labels: <none>
Annotations: deployment.kubernetes.io/revision: 2
kubectl.kubernetes.io/last-applied-configuration:
{"apiVersion":"apps/v1","kind":"Deployment","metadata":{"annotations":{},"name":"mynginx-deploy","namespace":"default"},"spec":{"replicas"...
kubernetes.io/change-cause: kubectl set image deployment mynginx-deploy nginx=nginx:1.9.1 --record=true
Selector: app=nginx
Replicas: 5 desired | 5 updated | 5 total | 5 available | 0 unavailable
StrategyType: RollingUpdate
MinReadySeconds: 0
RollingUpdateStrategy: 25% max unavailable, 25% max surge
Pod Template:
Labels: app=nginx
Containers:
nginx:
Image: nginx:1.9.1
Port: <none>
Host Port: <none>
Environment: <none>
Mounts: <none>
Volumes: <none>
Conditions:
Type Status Reason
---- ------ ------
Available True MinimumReplicasAvailable
Progressing True NewReplicaSetAvailable
OldReplicaSets: <none>
NewReplicaSet: mynginx-deploy-7f9686c8fd (5/5 replicas created)
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal ScalingReplicaSet 14m deployment-controller Scaled up replica set mynginx-deploy-55fbd9fd6d to 5
Normal ScalingReplicaSet 5m43s deployment-controller Scaled up replica set mynginx-deploy-7f9686c8fd to 2
Normal ScalingReplicaSet 5m43s deployment-controller Scaled down replica set mynginx-deploy-55fbd9fd6d to 4
Normal ScalingReplicaSet 5m43s deployment-controller Scaled up replica set mynginx-deploy-7f9686c8fd to 3
Normal ScalingReplicaSet 5m30s deployment-controller Scaled down replica set mynginx-deploy-55fbd9fd6d to 3
Normal ScalingReplicaSet 5m30s deployment-controller Scaled up replica set mynginx-deploy-7f9686c8fd to 4
Normal ScalingReplicaSet 5m28s deployment-controller Scaled down replica set mynginx-deploy-55fbd9fd6d to 2
Normal ScalingReplicaSet 5m28s deployment-controller Scaled up replica set mynginx-deploy-7f9686c8fd to 5
Normal ScalingReplicaSet 5m26s deployment-controller Scaled down replica set mynginx-deploy-55fbd9fd6d to 1
Normal ScalingReplicaSet 5m26s deployment-controller (combined from similar events): Scaled down replica set mynginx-deploy-55fbd9fd6d to 0
jinsu@jinsu:~$
# 롤백 기능
kubectl rollout undo deployment mynginx-deploy
# 해당 상태에서
jinsu@jinsu:~$ kubectl get pod
NAME READY STATUS RESTARTS AGE
mynginx-deploy-7f9686c8fd-fbtxv 1/1 Running 0 9m20s
mynginx-deploy-7f9686c8fd-h7pms 1/1 Running 0 9m7s
mynginx-deploy-7f9686c8fd-4q92b 1/1 Running 0 9m5s
mynginx-deploy-7f9686c8fd-vq8lt 1/1 Running 0 9m20s
mynginx-deploy-69d67779d8-zq7bz 0/1 ErrImagePull 0 45s
mynginx-deploy-69d67779d8-lxkhm 0/1 ErrImagePull 0 45s
mynginx-deploy-69d67779d8-jhvcm 0/1 ErrImagePull 0 45s
jinsu@jinsu:~$
# 롤백
jinsu@jinsu:~$ kubectl rollout undo deployment mynginx-deploy
deployment.apps/mynginx-deploy rolled back
jinsu@jinsu:~$
jinsu@jinsu:~$ kubectl get pod
NAME READY STATUS RESTARTS AGE
mynginx-deploy-7f9686c8fd-fbtxv 1/1 Running 0 13m
mynginx-deploy-7f9686c8fd-h7pms 1/1 Running 0 13m
mynginx-deploy-7f9686c8fd-4q92b 1/1 Running 0 13m
mynginx-deploy-7f9686c8fd-vq8lt 1/1 Running 0 13m
mynginx-deploy-7f9686c8fd-vn2gf 1/1 Running 0 13s
jinsu@jinsu:~$
# scaling 기능
kubectl scale deployment mynginx-deploy --replicas=5 --record
jinsu@jinsu:~$ kubectl scale deployment mynginx-deploy --replicas=10 --record
deployment.apps/mynginx-deploy scaled
jinsu@jinsu:~$
# pod가 10개로 생성
jinsu@jinsu:~$ kubectl get pod
NAME READY STATUS RESTARTS AGE
mynginx-deploy-7f9686c8fd-fbtxv 1/1 Running 0 15m
mynginx-deploy-7f9686c8fd-h7pms 1/1 Running 0 15m
mynginx-deploy-7f9686c8fd-4q92b 1/1 Running 0 15m
mynginx-deploy-7f9686c8fd-vq8lt 1/1 Running 0 15m
mynginx-deploy-7f9686c8fd-vn2gf 1/1 Running 0 2m11s
mynginx-deploy-7f9686c8fd-jxjrc 1/1 Running 0 15s
mynginx-deploy-7f9686c8fd-xv69q 1/1 Running 0 15s
mynginx-deploy-7f9686c8fd-r2dzt 1/1 Running 0 15s
mynginx-deploy-7f9686c8fd-vvvfp 1/1 Running 0 15s
mynginx-deploy-7f9686c8fd-576xz 1/1 Running 0 15s
jinsu@jinsu:~$
# 레플리카셋 확인
jinsu@jinsu:~$ kubectl get rs
NAME DESIRED CURRENT READY AGE
mynginx-deploy-55fbd9fd6d 0 0 0 25m
mynginx-deploy-69d67779d8 0 0 0 7m27s
mynginx-deploy-7f9686c8fd 10 10 10 16m
jinsu@jinsu:~$
deployment 삭제
# 현재 동작중인 deployment
jinsu@jinsu:~$ kubectl get deployment
NAME READY UP-TO-DATE AVAILABLE AGE
mynginx-deploy 5/5 5 4 25s
jinsu@jinsu:~$
# deployment 삭제
jinsu@jinsu:~$ kubectl delete deploy mynginx-deploy
deployment.apps "mynginx-deploy" deleted
jinsu@jinsu:~$
# 삭제되는 pod들
jinsu@jinsu:~$ kubectl get pod
NAME READY STATUS RESTARTS AGE
mynginx-deploy-7f9686c8fd-jxjrc 1/1 Terminating 0 2m23s
mynginx-deploy-7f9686c8fd-vq8lt 1/1 Terminating 0 17m
mynginx-deploy-7f9686c8fd-576xz 1/1 Terminating 0 2m23s
mynginx-deploy-7f9686c8fd-xv69q 1/1 Terminating 0 2m23s
mynginx-deploy-7f9686c8fd-vvvfp 1/1 Terminating 0 2m23s
jinsu@jinsu:~$
한번에 원하는 이미지로 deployment 생성
# 원하는 정보를 한번에 생성
kubectl create deployment httpd-frontend --image=httpd:2.4-alpine --replicas=3
레플리카셋의 목적은 레플리카 파드 집합의 실행을 항상 안정적으로 유지하는 것이다. 이처럼 레플리카셋은 보통 명시된 동일 파드 개수에 대한 가용성을 보증하는데 사용한다.
레플리카셋의 작동 방식
레플리카셋을 정의하는 필드는 획득 가능한 파드를 식별하는 방법이 명시된 셀렉터, 유지해야 하는 파드 개수를 명시하는 레플리카의 개수, 그리고 레플리카 수 유지를 위해 생성하는 신규 파드에 대한 데이터를 명시하는 파드 템플릿을 포함한다. 그러면 레플리카셋은 필드에 지정된 설정을 충족하기 위해 필요한 만큼 파드를 만들고 삭제한다. 레플리카셋이 새로운 파드를 생성해야 할 경우, 명시된 파드 템플릿을 사용한다.
레플리카셋은 파드의 metadata.ownerReferences 필드를 통해 파드에 연결되며, 이는 현재 오브젝트가 소유한 리소스를 명시한다. 레플리카셋이 가지고 있는 모든 파드의 ownerReferences 필드는 해당 파드를 소유한 레플리카셋을 식별하기 위한 소유자 정보를 가진다. 이 링크를 통해 레플리카셋은 자신이 유지하는 파드의 상태를 확인하고 이에 따라 관리 한다.
레플리카셋은 셀렉터를 이용해서 필요한 새 파드를 식별한다. 만약 파드에 OwnerReference이 없거나 OwnerReference가 컨트롤러(Controller) 가 아니고 레플리카셋의 셀렉터와 일치한다면 레플리카셋이 즉각 파드를 가지게 될 것이다.
레플리카셋은 언제 사용하는가?
레플리카셋은 지정된 수의 파드 레플리카가 항상 실행되도록 보장한다. 그러나 디플로이먼트는 레플리카셋을 관리하고 다른 유용한 기능과 함께 파드에 대한 선언적 업데이트를 제공하는 상위 개념이다. 따라서 우리는 사용자 지정 오케스트레이션이 필요하거나 업데이트가 전혀 필요하지 않은 경우라면 레플리카셋을 직접적으로 사용하기 보다는 디플로이먼트를 사용하는 것을 권장한다.
이는 레플리카셋 오브젝트를 직접 조작할 필요가 없다는 것을 의미한다. 대신 디플로이먼트를 이용하고 사양 부분에서 애플리케이션을 정의하면 된다
Replicaset 과 ReplicationController 의 차이점
복제 Pod를 만드는 역활은 둘다 똑같다.
Replicaset은 selector 기능으로 Label을 입력하여 Pods들을 보기쉽게, 효율적으로 관리할 수 있습니다.
레플리카셋 생성
# 레플리카셋 YAML파일 생성
jinsu@jinsu:~$ cat replicaset.yaml
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: mynginx-rs
spec:
replicas: 1
selector:
matchLabels:
app: mynginx-rs
template:
metadata:
labels:
app: mynginx-rs
spec:
containers:
- name: nginx
image: nginx
jinsu@jinsu:~$
jinsu@jinsu:~$ kubectl apply -f replicaset.yaml
replicaset.apps/mynginx-rs created
jinsu@jinsu:~$
# 레플리카셋 생성 확인
jinsu@jinsu:~$ kubectl get replicaset
NAME DESIRED CURRENT READY AGE
mynginx-rs 1 1 1 28s
jinsu@jinsu:~$
jinsu@jinsu:~$ kubectl get rs
NAME DESIRED CURRENT READY AGE
mynginx-rs 1 1 1 32s
jinsu@jinsu:~$
# 레플리카셋 pod 1개 생성 확인
jinsu@jinsu:~$ kubectl get pod
NAME READY STATUS RESTARTS AGE
mynginx-rs-hlw2j 1/1 Running 0 7m16s
jinsu@jinsu:~$
# 레플리카셋 설정값 확인
jinsu@jinsu:~$ kubectl get rs mynginx-rs -oyaml
apiVersion: apps/v1
kind: ReplicaSet
metadata:
annotations:
kubectl.kubernetes.io/last-applied-configuration: |
{"apiVersion":"apps/v1","kind":"ReplicaSet","metadata":{"annotations":{},"name":"mynginx-rs","namespace":"default"},"spec":{"replicas":1,"selector":{"matchLabels":{"app":"mynginx-rs"}},"template":{"metadata":{"labels":{"app":"mynginx-rs"}},"spec":{"containers":[{"image":"nginx","name":"nginx"}]}}}}
creationTimestamp: "2022-08-14T07:40:17Z"
generation: 1
name: mynginx-rs
namespace: default
resourceVersion: "13994"
selfLink: /apis/apps/v1/namespaces/default/replicasets/mynginx-rs
uid: ad48f6a2-ef69-403b-b96a-5cefa8d94372
spec:
replicas: 1
selector:
matchLabels:
app: mynginx-rs
template:
metadata:
creationTimestamp: null
labels:
app: mynginx-rs
spec:
containers:
- image: nginx
imagePullPolicy: Always
name: nginx
resources: {}
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
dnsPolicy: ClusterFirst
restartPolicy: Always
schedulerName: default-scheduler
securityContext: {}
terminationGracePeriodSeconds: 30
status:
availableReplicas: 1
fullyLabeledReplicas: 1
observedGeneration: 1
readyReplicas: 1
replicas: 1
jinsu@jinsu:~$
# 레플리카셋에 pod 생성을 2개로 설정(spec: replicas: 2)
jinsu@jinsu:~$ kubectl get rs mynginx-rs -oyaml
apiVersion: apps/v1
kind: ReplicaSet
metadata:
annotations:
kubectl.kubernetes.io/last-applied-configuration: |
{"apiVersion":"apps/v1","kind":"ReplicaSet","metadata":{"annotations":{},"name":"mynginx-rs","namespace":"default"},"spec":{"replicas":1,"selector":{"matchLabels":{"app":"mynginx-rs"}},"template":{"metadata":{"labels":{"app":"mynginx-rs"}},"spec":{"containers":[{"image":"nginx","name":"nginx"}]}}}}
creationTimestamp: "2022-08-14T07:40:17Z"
generation: 2
name: mynginx-rs
namespace: default
resourceVersion: "14633"
selfLink: /apis/apps/v1/namespaces/default/replicasets/mynginx-rs
uid: ad48f6a2-ef69-403b-b96a-5cefa8d94372
spec:
replicas: 2
# 설정값을 변경하자마자 pod가 2개로 생성
jinsu@jinsu:~$ kubectl get pod
NAME READY STATUS RESTARTS AGE
mynginx-rs-hlw2j 1/1 Running 0 13m
mynginx-rs-t8wx2 1/1 Running 0 10s
jinsu@jinsu:~$
jinsu@jinsu:~$ kubectl get rs
NAME DESIRED CURRENT READY AGE
mynginx-rs 2 2 2 13m
jinsu@jinsu:~$
레플리카셋 삭제
# 현재 동작중인 레플리카셋 확인
jinsu@jinsu:~$ kubectl get rs
NAME DESIRED CURRENT READY AGE
mynginx-rs 2 2 2 42m
jinsu@jinsu:~$
# 레플리카셋 삭제
jinsu@jinsu:~$ kubectl delete rs mynginx-rs
replicaset.apps "mynginx-rs" deleted
jinsu@jinsu:~$
jinsu@jinsu:~$ kubectl get rs
No resources found in default namespace.
jinsu@jinsu:~$
레플리카셋 Scale 수정
# Replicaset 만들었던 Yaml 파일 수정하여 replace
kubectl replace -f replicaset-definition.yaml
# scale 명령으로 레플리카셋 3에서 6으로 수정
kubectl scale --replicas=6 -f replicaset-definition.yaml
# scale 명령으로 name을 지정해서 수정
kubectl scale --replicas=6 replicaset myapp-replicaset
동작중인 레플리카셋 정보를 수정 및 yaml로 생성
# 현재 동작중인 replicaset을 edit으로 수정
kubectl edit replicaset new-replica-set
# 현재 동작중인 replicaset을 yaml파일로 변경
kubectl get replicaset new-replica-set -o yaml > new-replica-set.yaml
쿠버네티스는 Pod에게 고유한 IP 주소와 Pod 집합에 대한 단일 DNS 명을 부여하고, 그것들 간에 로드밸런싱을 수행할 수 있다
서비스 리소스
쿠버네티스에서 Service는 Pod의 논리적으로 분리된 집합과 그 집합에 접근할 수 있는 정책을 정의하는 개념이다. (때로는 이 패턴을 마이크로-서비스라고 한다.)
서비스가 대상으로 하는 파드 집합은 일반적으로 Selector가 결정한다. 서비스 엔드포인트를 정의하는 다른 방법에 대한 자세한 내용은 셀렉터가 없는 서비스를 참고한다.
서비스 정의
쿠버네티스의 서비스는 파드와 비슷한 REST 오브젝트이다.
모든 REST 오브젝트와 마찬가지로, 서비스 정의를 API 서버에 POST하여 새 인스턴스를 생성할 수 있다.
서비스 오브젝트의 이름은 유효한 RFC 1035 레이블 이름이어야 한다.
Service 연동
# 먼저 nginx를 띄울 pod를 생성해줍니다.
jinsu@jinsu:~$ kubectl run mynginx --image nginx --restart Never
pod/mynginx created
jinsu@jinsu:~$
jinsu@jinsu:~$ kubectl get pod
NAME READY STATUS RESTARTS AGE
mynginx 1/1 Running 0 6s
jinsu@jinsu:~$
# Service를 만든 후 실행
jinsu@jinsu:~$ cat Service.yaml
apiVersion: v1
kind: Service
metadata:
name: mynginx
spec:
ports:
- port: 80
protocol: TCP
targetPort: 80
selector:
run: mynginx
jinsu@jinsu:~$
jinsu@jinsu:~$ kubectl apply -f Service.yaml
service/mynginx unchanged
jinsu@jinsu:~$
# mynginx 서비스가 잘 동작중인걸 확인
jinsu@jinsu:~$ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.43.0.1 <none> 443/TCP 144m
mynginx ClusterIP 10.43.42.124 <none> 80/TCP 32m
jinsu@jinsu:~$
# client pod에 들어가 dns를 설치
jinsu@jinsu:~$ kubectl exec -it client -- bash
root@client:/# apt update && apt install -y dnsutils
# nslookup을 해보면 mynginx를 만들었던 pod의 dns가 보이는 걸 확인
root@client:/# nslookup mynginx
Server: 10.43.0.10
Address: 10.43.0.10#53
Name: mynginx.default.svc.cluster.local
Address: 10.43.42.124
root@client:/# nslookup mynginx.default
Server: 10.43.0.10
Address: 10.43.0.10#53
Name: mynginx.default.svc.cluster.local
Address: 10.43.42.124
root@client:/#
# nginx 동작 확인
root@client:/# curl mynginx
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
root@client:/#
서비스 타입 (ServiceTypes)
Pod내의 애플리케이션 중 일부는 서비스를 클러스터 밖에 위치한 외부 IP 주소에 노출하고 싶은 경우가 있을 것이다.
쿠버네티스 ServiceTypes는 원하는 서비스 종류를 지정할 수 있도록 해준다. 기본 값은 ClusterIP이다.
Type 값과 그 동작은 다음과 같다.
ClusterIP- 서비스를 클러스터-내부 IP에 노출시킨다. 이 값을 선택하면 클러스터 내에서만 서비스에 도달할 수 있다. 이것은 ServiceTypes의 기본 값이다.
NodePort- 고정 포트 (NodePort)로 각 노드의 IP에 서비스를 노출시킨다. NodePort 서비스가 라우팅되는 ClusterIP 서비스가 자동으로 생성된다. <NodeIP>:<NodePort>를 요청하여, 클러스터 외부에서 NodePort 서비스에 접속할 수 있다.
LoadBalancer- 클라우드 공급자의 로드 밸런서를 사용하여 서비스를 외부에 노출시킨다. 외부 로드 밸런서가 라우팅되는 NodePort와 ClusterIP 서비스가 자동으로 생성된다.
ExternalName - 값과 함께 CNAME 레코드를 리턴하여, 서비스를 externalName 필드의 콘텐츠 (예:foo.bar.example.com)에 매핑한다. 어떤 종류의 프록시도 설정되어 있지 않다.
참고: ExternalName 유형을 사용하려면 kube-dns 버전 1.7 또는 CoreDNS 버전 1.7 이상이 필요하다.
인그레스를 사용하여 서비스를 노출시킬 수도 있다. 인그레스는 서비스 유형이 아니지만, 클러스터의 진입점 역할을 한다. 동일한 IP 주소로 여러 서비스를 노출시킬 수 있기 때문에 라우팅 규칙을 단일 리소스로 통합할 수 있다.
NodePort 유형
type 필드를 NodePort로 설정하면, 쿠버네티스 컨트롤 플레인은 --service-node-port-range 플래그로 지정된 범위에서 포트를 할당한다 (기본값 : 30000-32767). 각 노드는 해당 포트 (모든 노드에서 동일한 포트 번호)를 서비스로 프록시한다. 서비스는 할당된 포트를 .spec.ports[*].nodePort 필드에 나타낸다.
포트를 프록시하기 위해 특정 IP를 지정하려면, kube-proxy에 대한 --nodeport-addresses 플래그 또는 kube-proxy 구성 파일의 동등한 nodePortAddresses 필드를 특정 IP 블록으로 설정할 수 있다.
이 플래그는 쉼표로 구분된 IP 블록 목록(예: 10.0.0.0/8, 192.0.2.0/25)을 사용하여 kube-proxy가 로컬 노드로 고려해야 하는 IP 주소 범위를 지정한다.
예를 들어, --nodeport-addresses=127.0.0.0/8 플래그로 kube-proxy를 시작하면, kube-proxy는 NodePort 서비스에 대하여 루프백(loopback) 인터페이스만 선택한다. --nodeport-addresses의 기본 값은 비어있는 목록이다. 이것은 kube-proxy가 NodePort에 대해 사용 가능한 모든 네트워크 인터페이스를 고려해야 한다는 것을 의미한다. (이는 이전 쿠버네티스 릴리스와도 호환된다).
특정 포트 번호를 원한다면, nodePort 필드에 값을 지정할 수 있다. 컨트롤 플레인은 해당 포트를 할당하거나 API 트랜잭션이 실패했다고 보고한다. 이는 사용자 스스로 포트 충돌의 가능성을 고려해야 한다는 의미이다. 또한 NodePort 사용을 위해 구성된 범위 내에 있는, 유효한 포트 번호를 사용해야 한다.
NodePort를 사용하면 자유롭게 자체 로드 밸런싱 솔루션을 설정하거나, 쿠버네티스가 완벽하게 지원하지 않는 환경을 구성하거나, 하나 이상의 노드 IP를 직접 노출시킬 수 있다.
이 서비스는 <NodeIP>:spec.ports[*].nodePort와 .spec.clusterIP:spec.ports[*].port로 표기된다. kube-proxy에 대한 --nodeport-addresses 플래그 또는 kube-proxy 구성 파일의 동등한 필드가 설정된 경우, <NodeIP> 는 노드 IP를 필터링한다.
Service IP 서비스
# mynginx IP로 서비스를 연동
jinsu@jinsu:~$ kubectl get pod -owide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
mynginx 1/1 Running 0 103m 10.42.0.15 master <none> <none>
busybox 1/1 Running 0 12m 10.42.0.20 master <none> <none>
curl 0/1 CrashLoopBackOff 7 14m 10.42.0.19 master <none> <none>
jinsu@jinsu:~$
# args 부분에 연동할 pod의 IP를 입력
jinsu@jinsu:~$ cat curl.yaml
apiVersion: v1
kind: Pod
metadata:
name: curl
spec:
containers:
- name: curl
image: curlimages/curl
command: ["curl"]
args: ["10.42.0.15"]
jinsu@jinsu:~$
# pod를 생성
insu@jinsu:~$ kubectl apply -f curl.yaml
pod/curl created
jinsu@jinsu:~$
# logs로 확인했을때 nginx 와 통신 확인
jinsu@jinsu:~$ kubectl get pod
NAME READY STATUS RESTARTS AGE
mynginx 1/1 Running 0 82m
curl 0/1 CrashLoopBackOff 1 12s
jinsu@jinsu:~$ kubectl logs curl
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 615 100 615 0 0 1918k 0 --:--:-- --:--:-- --:--:-- 600k
# nginx pod에도 연결 확인
jinsu@jinsu:~$ kubectl logs mynginx
/docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
/docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
/docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
10-listen-on-ipv6-by-default.sh: info: Getting the checksum of /etc/nginx/conf.d/default.conf
10-listen-on-ipv6-by-default.sh: info: Enabled listen on IPv6 in /etc/nginx/conf.d/default.conf
/docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
/docker-entrypoint.sh: Launching /docker-entrypoint.d/30-tune-worker-processes.sh
/docker-entrypoint.sh: Configuration complete; ready for start up
2022/08/14 04:52:51 [notice] 1#1: using the "epoll" event method
2022/08/14 04:52:51 [notice] 1#1: nginx/1.23.1
2022/08/14 04:52:51 [notice] 1#1: built by gcc 10.2.1 20210110 (Debian 10.2.1-6)
2022/08/14 04:52:51 [notice] 1#1: OS: Linux 4.15.0-191-generic
2022/08/14 04:52:51 [notice] 1#1: getrlimit(RLIMIT_NOFILE): 1048576:1048576
2022/08/14 04:52:51 [notice] 1#1: start worker processes
2022/08/14 04:52:51 [notice] 1#1: start worker process 32
2022/08/14 04:52:51 [notice] 1#1: start worker process 33
2022/08/14 04:52:51 [notice] 1#1: start worker process 34
2022/08/14 04:52:51 [notice] 1#1: start worker process 35
10.42.0.16 - - [14/Aug/2022:04:56:07 +0000] "GET / HTTP/1.1" 200 615 "-" "curl/7.84.0-DEV" "-"
10.42.0.16 - - [14/Aug/2022:04:56:10 +0000] "GET / HTTP/1.1" 200 615 "-" "curl/7.84.0-DEV" "-"
Cluster IP 서비스
# Service.yaml 파일 생성 ClusterIP를 입력안할경우 delfault로 적용
jinsu@jinsu:~$ cat Service.yaml
apiVersion: v1
kind: Service
metadata:
name: mynginx
spec:
ports:
- port: 80
protocol: TCP
targetPort: 80
selector:
run: mynginx
jinsu@jinsu:~$
# Service 생성 및 상태확인
jinsu@jinsu:~$ kubectl apply -f Service.yaml
service/mynginx unchanged
jinsu@jinsu:~$ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.43.0.1 <none> 443/TCP 4h45m
mynginx ClusterIP 10.43.42.124 <none> 80/TCP 173m
jinsu@jinsu:~$
# Service CLUSTER-IP를 입력해서 연동
jinsu@jinsu:~$ cat curl.yaml
apiVersion: v1
kind: Pod
metadata:
name: curl
spec:
containers:
- name: curl
image: curlimages/curl
command: ["curl"]
args: [ "10.43.42.124" ]
jinsu@jinsu:~$
# curl 생성 및 상태 확인
jinsu@jinsu:~$ kubectl apply -f curl.yaml
pod/curl created
jinsu@jinsu:~$ kubectl get pod
NAME READY STATUS RESTARTS AGE
mynginx 1/1 Running 0 89m
curl 0/1 CrashLoopBackOff 1 12s
jinsu@jinsu:~$
# curl logs 확인시 통신 확인
jinsu@jinsu:~$ kubectl logs curl
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 615 100 615 0 0 523k 0 --:--:-- --:--:-- --:--:-- 600k
# nginx logs 확인시 통신 확인
jinsu@jinsu:~$ kubectl logs mynginx
/docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
/docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
/docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
10-listen-on-ipv6-by-default.sh: info: Getting the checksum of /etc/nginx/conf.d/default.conf
10-listen-on-ipv6-by-default.sh: info: Enabled listen on IPv6 in /etc/nginx/conf.d/default.conf
/docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
/docker-entrypoint.sh: Launching /docker-entrypoint.d/30-tune-worker-processes.sh
/docker-entrypoint.sh: Configuration complete; ready for start up
2022/08/14 04:52:51 [notice] 1#1: using the "epoll" event method
2022/08/14 04:52:51 [notice] 1#1: nginx/1.23.1
2022/08/14 04:52:51 [notice] 1#1: built by gcc 10.2.1 20210110 (Debian 10.2.1-6)
2022/08/14 04:52:51 [notice] 1#1: OS: Linux 4.15.0-191-generic
2022/08/14 04:52:51 [notice] 1#1: getrlimit(RLIMIT_NOFILE): 1048576:1048576
2022/08/14 04:52:51 [notice] 1#1: start worker processes
2022/08/14 04:52:51 [notice] 1#1: start worker process 32
2022/08/14 04:52:51 [notice] 1#1: start worker process 33
2022/08/14 04:52:51 [notice] 1#1: start worker process 34
2022/08/14 04:52:51 [notice] 1#1: start worker process 35
10.42.0.19 - - [14/Aug/2022:06:21:39 +0000] "GET / HTTP/1.1" 200 615 "-" "curl/7.84.0-DEV" "-"
10.42.0.19 - - [14/Aug/2022:06:21:43 +0000] "GET / HTTP/1.1" 200 615 "-" "curl/7.84.0-DEV" "-"
10.42.0.19 - - [14/Aug/2022:06:21:58 +0000] "GET / HTTP/1.1" 200 615 "-" "curl/7.84.0-DEV" "-"
NodePort 서비스
# 기존에 사용중인 서비스가 ClusterIP TYPE
jinsu@jinsu:~$ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.43.0.1 <none> 443/TCP 4h51m
mynginx ClusterIP 10.43.42.124 <none> 80/TCP 179m
jinsu@jinsu:~$
# Service를 edit 수정하여 nodePort, type을 변경
jinsu@jinsu:~$ kubectl edit service mynginx
# Please edit the object below. Lines beginning with a '#' will be ignored,
# and an empty file will abort the edit. If an error occurs while saving this file will be
# reopened with the relevant failures.
#
apiVersion: v1
kind: Service
metadata:
annotations:
kubectl.kubernetes.io/last-applied-configuration: |
{"apiVersion":"v1","kind":"Service","metadata":{"annotations":{},"name":"mynginx","namespace":"default"},"spec":{"ports":[
creationTimestamp: "2022-08-14T03:24:02Z"
name: mynginx
namespace: default
resourceVersion: "11731"
selfLink: /api/v1/namespaces/default/services/mynginx
uid: b11eaf09-9376-4e90-adb3-75d9a7754dd1
spec:
clusterIP: 10.43.42.124
externalTrafficPolicy: Cluster
ports:
- nodePort: 30080
port: 80
protocol: TCP
targetPort: 80
selector:
run: mynginx
sessionAffinity: None
type: NodePort
status:
loadBalancer: {}
# TYPE이 NodePort로 변경
jinsu@jinsu:~$ kubectl get service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.43.0.1 <none> 443/TCP 5h27m
mynginx NodePort 10.43.42.124 <none> 80:30080/TCP 3h35m
jinsu@jinsu:~$
# 본인 Kubernetes 서버 IP 확인
jinsu@jinsu:~$ ifconfig
ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 192.168.0.211 netmask 255.255.255.0 broadcast 192.168.0.255
# IP에 Port를 입력해서 nginx 동작 확인
jinsu@jinsu:~$ curl 192.168.0.211:30080
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
jinsu@jinsu:~$
LoadBalancer 서비스
# type을 LoadBalancer로 변경 후 저장
jinsu@jinsu:~$ kubectl get service mynginx -oyaml
apiVersion: v1
kind: Service
metadata:
annotations:
kubectl.kubernetes.io/last-applied-configuration: |
{"apiVersion":"v1","kind":"Service","metadata":{"annotations":{},"name":"mynginx","namespace":"default"},"spec":{"ports":[{"port":80,"protocol":"TCP","targetPort":80}],"selector":{"run":"mynginx"}}}
creationTimestamp: "2022-08-14T03:24:02Z"
name: mynginx
namespace: default
resourceVersion: "12339"
selfLink: /api/v1/namespaces/default/services/mynginx
uid: b11eaf09-9376-4e90-adb3-75d9a7754dd1
spec:
clusterIP: 10.43.42.124
externalTrafficPolicy: Cluster
ports:
- nodePort: 30080
port: 80
protocol: TCP
targetPort: 80
selector:
run: mynginx
sessionAffinity: None
type: LoadBalancer
status:
loadBalancer:
ingress:
- ip: 192.168.0.211
jinsu@jinsu:~$
# 서비스 상태 확인
jinsu@jinsu:~$ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.43.0.1 <none> 443/TCP 5h32m
mynginx LoadBalancer 10.43.42.124 192.168.0.211 80:30080/TCP 3h40m
jinsu@jinsu:~$
# EXTERNAL-IP로 확인해보면 nginx 서비스 동작 확인
jinsu@jinsu:~$ curl 192.168.0.211
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
jinsu@jinsu:~$
ExternalName 서비스
# external 서비스를 google 도메인으로 생성
jinsu@jinsu:~$ cat external.yaml
apiVersion: v1
kind: Service
metadata:
name: my-google-svc
spec:
type: ExternalName
externalName: google.com
jinsu@jinsu:~$
jinsu@jinsu:~$ kubectl apply -f external.yaml
service/my-google-svc created
jinsu@jinsu:~$
# google도메인으로 externalName 만든 서비스 확인
jinsu@jinsu:~$ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.43.0.1 <none> 443/TCP 5h37m
mynginx LoadBalancer 10.43.42.124 192.168.0.211 80:30080/TCP 3h45m
my-google-svc ExternalName <none> google.com <none> 8s
jinsu@jinsu:~$
# google로 생성한 pod랑 연동
jinsu@jinsu:~$ cat curl.yaml
apiVersion: v1
kind: Pod
metadata:
name: curl
spec:
containers:
- name: curl
image: curlimages/curl
command: ["curl"]
args: [ "my-google-svc" ]
jinsu@jinsu:~$
jinsu@jinsu:~$ kubectl apply -f curl.yaml
pod/curl created
jinsu@jinsu:~$
# logs를 확인해보면 google도메인으로 연동 확인
jinsu@jinsu:~$ kubectl logs curl
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 1561 100 1561 0 0 19763 0 --:--:-- --:--:-- --:--:-- 20012
<!DOCTYPE html>
<html lang=en>
<meta charset=utf-8>
<meta name=viewport content="initial-scale=1, minimum-scale=1, width=device-width">
<title>Error 404 (Not Found)!!1</title>
<style>
*{margin:0;padding:0}html,code{font:15px/22px arial,sans-serif}html{background:#fff;color:#222;padding:15px}body{margin:7% auto 0;max-width:390px;min-height:180px;padding:30px 0 15px}* > body{background:url(//www.google.com/images/errors/robot.png) 100% 5px no-repeat;padding-right:205px}p{margin:11px 0 22px;overflow:hidden}ins{color:#777;text-decoration:none}a img{border:0}@media screen and (max-width:772px){body{background:none;margin-top:0;max-width:none;padding-right:0}}#logo{background:url(//www.google.com/images/branding/googlelogo/1x/googlelogo_color_150x54dp.png) no-repeat;margin-left:-5px}@media only screen and (min-resolution:192dpi){#logo{background:url(//www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png) no-repeat 0% 0%/100% 100%;-moz-border-image:url(//www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png) 0}}@media only screen and (-webkit-min-device-pixel-ratio:2){#logo{background:url(//www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png) no-repeat;-webkit-background-size:100% 100%}}#logo{display:inline-block;height:54px;width:150px}
</style>
<a href=//www.google.com/><span id=logo aria-label=Google></span></a>
<p><b>404.</b> <ins>That’s an error.</ins>
<p>The requested URL <code>/</code> was not found on this server. <ins>That’s all we know.</ins>
jinsu@jinsu:~$