Learning Kubernetes
[toc]
3. 도커 기본 다지기
3.1 도커 설치하기
3.1.1 Ubuntu 설치
sudo apt-get update
sudo apt-get install docker.io
sudo ln -sf /usr/bin/docker.io /usr/local/bin/docker
우분투 패키지 메니저는 apt-get , apt-cache, apt 가 있습니다. 모두 동일한 명령어라고 보면 되지만, apt 를 쓸경우 일단 글자수가 적고, 출력 Output 에 색상이 추가되어 좀더 예쁘게 보입니다.
3.1.2 CentOS 6
sudo yum install http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm
sudo yum install docker-io
3.1.3 CentOS 7
sudo yum install docker
sudo service docker start
sudo chkconfig docker on # 부팅시에 자동 스타트업
3.1.4 Mac 및 Windows 에 설치
아래 URL 에서 다운받아 설치 하면 됩니다.
MAC 의 경우 Hyperkit, Windows 의 경우 Hyper-V 를 가상화 레이어로 사용 합니다.
Docker Desktop for Mac : https://hub.docker.com/editions/community/docker-ce-desktop-mac/
Docker Desktop for Windows : https://hub.docker.com/editions/community/docker-ce-desktop-windows/
3.2 도커 기본 명령어
도커 파일 내에서 사용 가능한 명령어
명령 | 설명 | 명령 | 설명 |
---|---|---|---|
FROM | 베이스 이미지 지정 | VOLUME | 볼륨 마운트 |
RUN | 명령실행 | USER | 사용자 지정 |
CMD | 컨테이너 실행 명령 | WORKDIR | 작업 디렉토리 |
LABEL | 라벨 설정 | ONBUILD | Dockerfile 내의 변수 |
EXPOSE | 포트 익스포트 | STOPSIGNAL | 빌드 완료 후 실행되는 명령 |
ENV | 환경변수 | HEALTHCHECK | 시스템 콜 시그널 설정 |
ADD | 파일/디렉토리 추가 | SHELL | 기본 쉘 설정 |
CPOY | 파일 복사 | ||
ENTRYPOINT | 컨테이너 실행 명령사 |
3.2.1 도커 hub 사용을 위한 계정생성
sudo docker login
docker hub (hub.docker.dom) 에 가입 후 명령어를 실행 해야 로그인이 가능 합니다.
3.2.2 도커 이미지 검색
search 명령으로 nginx 를 검색해 봅니다.
sudo docker search nginx
3.2.3 도커 이미지 다운로드
nodejs 이미지를 설치해봅니다. 최신 안정버전인 12.14 버전을 설치 합니다.
sudo docker pull nodejs:latest # 최신버전 다운로드
sudo docker pull nodejs:12.14.0 # 특정버전 다운로드
sudo docker pull -a nodejs # 모든버전 다운로드
3.2.4 도커 이미지 목록 보기
docker image list
docker image ls
docker images
3.3 도커 이미지 생성 하기
3.3.1 서비스를 위한 Application 코드 작성
hostname_finder 라는 폴더를 만들고 그 아래 main.go 및 Dockerfiles 2개 파일을 작성 합니다.
먼저 vi 또는 gedit 를 실행해서 아래 파일을 main.go 라는 이름 으로 작성 합니다.
package main
import (
"fmt"
"os"
"log"
"net/http"
)
func handler(w http.ResponseWriter, r *http.Request){
name, err := os.Hostname()
if err != nil {
panic(err)
}
fmt.Fprintln(w,"hostname:", name)
}
func main() {
fmt.Fprintln(os.Stdout,"Starting GoApp Server......")
http.HandleFunc("/",handler)
log.Fatal(http.ListenAndServe(":8080",nil))
}
3.3.2 이미지 생성을 위한 Dockerfile 작성
FROM golang:1.11-alpine AS build
WORKDIR /src/
COPY main.go go.* /src/
RUN CGO_ENABLED=0 go build -o /bin/demo
FROM scratch
COPY --from=build /bin/demo /bin/demo
ENTRYPOINT ["/bin/demo"]
3.3.3 컨테이너 이미지 생성
hostname_finder 라는 폴더 안에서 아래 명령어를 실행 합니다.
docker build -t goapp .
. 은 현재 디렉토리서 Dockerfile 참조해서 first-container 라는 이미지를 생성 합니다.
[출력]
Sending build context to Docker daemon 3.072kB
Step 1/7 : FROM golang:1.11-alpine AS build
---> e116d2efa2ab
Step 2/7 : WORKDIR /src/
---> Using cachedocker
---> c3210d8eb11f
Step 3/7 : COPY main.go go.* /src/
---> ef55118ea78c
Step 4/7 : RUN CGO_ENABLED=0 go build -o /bin/demo
---> Running in e557730bf11c
Removing intermediate container e557730bf11c
---> d55bd9bd3f81
Step 5/7 : FROM scratch
--->
Step 6/7 : COPY --from=build /bin/demo /bin/demo
---> bb4b1250a05e
Step 7/7 : ENTRYPOINT ["/bin/demo"]
---> Running in 4419d56988aa
Removing intermediate container 4419d56988aa
---> 36f5c919e3b8
Successfully built 36f5c919e3b8
Successfully tagged goapp:latest
이미지가 생성 되었는지 명령어를 통해 확인 합니다.
docker images
[출력]
REPOSITORY TAG IMAGE ID CREATED SIZE
<none> <none> d55bd9bd3f81 About a minute ago 325MB
goapp latest 36f5c919e3b8 About a minute ago 6.51MB
<none> <none> 1c688e9c7e3c 3 days ago 325MB
<none> <none> 9b60c66a5b82 3 days ago 6.51MB
<none> <none> 7fc44021a96f 3 days ago 325MB
<none> <none> 2caa0c2ac791 3 days ago 325MB
<none> <none> c46d81105b65 3 days ago 6.51MB
<none> <none> 2d78705fb4ae 3 days ago 312MB
3.4 도커 컨테이너 시작 및 서비스 확인
3.4.1 도커 컨테이너 시작
docker run --name goapp-project -p 8080:8080 -d goapp
docker run -it --name goapp-project -p 8080:8080 -d goapp /bin/bash
–name : 실행한 도커 컨테이너의 이름 지정
-p : 포트 맵핑 정보 localhost 와 컨테이너 포트를 맵핑 합니다.
-d : Docker 컨테이너를 백그라운드로 수행하고 컨테이너 ID를 출력 합니다.
-i : STDIN 계속 interactive 모드로 유지
3.4.2 도커 컨테이스 서비스 확인
curl 명령어를 통해 정상적인 서비스 수행 여부를 확인 합니다.
curl localhost:8080
[출력]
hostname: 96fc3a5eb914
3.4.3 도커 프로세서 확인
docker ps
[출력]
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
96fc3a5eb914 goapp "/bin/demo" 43 seconds ago Up 42 seconds 0.0.0.0:8080->8080/tcp goapp-project
3.4.4 프로세서 상세 정보 출력
docker inspect goapp-project
[출력]
[
{
"Id": "96fc3a5eb914c58ed83e088681d53a46188edeaab061ff2de0b9852e9dd276c9",
"Created": "2020-01-10T04:32:12.269012485Z",
"Path": "/bin/demo",
"Args": [],
"State": {
"Status": "running",
"Running": true,
"Paused": false,
"Restarting": false,
"OOMKilled": false,
"Dead": false,
"Pid": 31285,
"ExitCode": 0,
"Error": "",
"StartedAt": "2020-01-10T04:32:12.902395362Z",
"FinishedAt": "0001-01-01T00:00:00Z"
},
"Image": "sha256:36f5c919e3b88f1c991eda67d96e62fe02b763182e44f19fb78b2fc055165f3d",
"ResolvConfPath": "/var/lib/docker/containers/96fc3a5eb914c58ed83e088681d53a46188edeaab061ff2de0b9852e9dd276c9/resolv.conf",
"HostnamePath": "/var/lib/docker/containers/96fc3a5eb914c58ed83e088681d53a46188edeaab061ff2de0b9852e9dd276c9/hostname",
"HostsPath": "/var/lib/docker/containers/96fc3a5eb914c58ed83e088681d53a46188edeaab061ff2de0b9852e9dd276c9/hosts",
"LogPath": "/var/lib/docker/containers/96fc3a5eb914c58ed83e088681d53a46188edeaab061ff2de0b9852e9dd276c9/96fc3a5eb914c58ed83e088681d53a46188edeaab061ff2de0b9852e9dd276c9-json.log",
3.4.5 Docker 컨테이너 접속
# docker 컨테이너 접속
docker exec -it goapp-project bash
# docker 외부에서 컨테이너에 명령수행 (ls 명령 수행)
docker exec goapp-project ls
-i 또는 –interactive : STDIN을 오픈한 상태로 인터랙티브 모드상태
-t 또는 –tty : terminal 모드
container 이름이 보이지 않고 ID 만 기본적으로 보입니다. 컨테이너 이름을 출력하려면 아래 명령어를 수행 하면 됩니다.
docker ps –format ""
3.4.6 도커 인스턴스 중단 및 삭제
docker stop goapp-project
docker rm goapp-project
3.5. 도커 이미지를 도커 허브에 업로드
3.5.1 도커 허브양식에 맞게 tag 수정하기
docker tag goapp dangtong/goapp
[출력]
REPOSITORY TAG IMAGE ID CREATED SIZE
dangtong/goapp latest 12e9a84d9e23 3 days ago 6.51MB
goapp latest 12e9a84d9e23 3 days ago 6.51MB
dangtong/firstapp 과 first-container 의 image ID 가 같은 것을 확인 할 수 있습니다.
사실 하나의 이미지를 서로 다른 TAGID 로 공유 하는 것입니다. 디스크 공간이 늘어나지 않습니다.
3.5.2 도커 허브에 이미지 업로드 하기
docker login --username dangtong
docker push dangtong/goapp
[출력]
The push refers to repository [docker.io/dangtong/goapp]
cc282a374c26: Pushed
latest: digest: sha256:b18b5ff03599893a7361feda054ebe26de61a71f019dc8725bb33d87f2115968 size: 528
도커 허브에 로그인 하게 되면 아래와 같이 goapp 이미지가 업로드 된것을 확인 할 수 있습니다. 이제 인터넷만 연결 되면 어디서는 자신이 만든 이미지로 컨테이너를 실행 할 수 있습니다.
3.5.3 도커 허브의 이미지로 컨테이너 실행
docker hub 에 있는 이미지를 로딩하여 컨테이너 생성
docker run --name goapp-project -p 8080:8080 -d dangtong/goapp
docker ps
[출력]
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
0938068f8709 dangtong/goapp "/bin/demo" 5 seconds ago Up 4 seconds 0.0.0.0:8080->8080/tcp goapp-project
현재 서비스에 접속하여 확인
curl http://localhost:8080
hostname: 0938068f8709
[Exercise #1]
-
서버 호스트명을 출력하는 node.js 프로그램을 만드세요
-
해당 소스로 node 버전 7 기반으로 서비스 하는 Docker file을 만들고 이미지를 build 하세요
-
tag 명령을 이용해서 docker hub 에 올릴수 있도록 이름을 바꾸세요
-
docker login 후에 docker hub 에 업로드하여 실제 업로드가 되었는지 확인하세요
이름은 username/nodejs-app 으로 하세요
- node.js 프로그램 (app.js)
const http = require('http');
const os = require('os');
console.log("Learning Kubernetes server starting...");
var handler = function(request, response) {
console.log("Received request from " + request.connection.remoteAddress);
response.writeHead(200);
response.end("You've hit " + os.hostname() + "\n");
};
var www = http.createServer(handler);
www.listen(8080);
- Dcokerfile
# FROM 으로 BASE 이미지 로드
FROM node:7
# ADD 명령어로 이미지에 app.js 파일 추가
ADD app.js /app.js
# ENTRYPOINT 명령어로 node 를 실행하고 매개변수로 app.js 를 전달
ENTRYPOINT ["node", "app.js"]
4. 쿠버네티스 간단하게 맛보기
4.1 도커 허브 이미지로 컨테이너 생성 및 확인
-
컨테이너 생성 : run/v1 으로 수행 합니다.
# POD 및 Replication Controller 생성 (향후 버전에서 deprecated 될 예정) $ kubectl run goapp-project --image=dangtong/goapp --port=8080 --generator=run/v1 # POD 만 생성 $ kubectl run goapp-project --image=dangtong/goapp --port=8080 --generator=run-pod/v1
generator 를 run/v1 으로 수행 할 경우 내부적으로 goapp-project-{random-String} 이라는 컨테이너를 만들면서 goapp-project- 이름의 replication controller 도 생기게 됩니다.
- Generator 의 종류 : run-pod/v1 외에 모두 deprecated 될 예정
Resource API group kubectl command Pod v1 kubectl run --generator=run-pod/v1
ReplicationController (deprecated) v1 kubectl run --generator=run/v1
Deployment (deprecated) extensions/v1beta1 kubectl run --generator=deployment/v1beta1
Deployment (deprecated) apps/v1beta1 kubectl run --generator=deployment/apps.v1beta1
Job (deprecated) batch/v1 kubectl run --generator=job/v1
CronJob (deprecated) batch/v2alpha1 kubectl run --generator=cronjob/v2alpha1
CronJob (deprecated) batch/v1beta1 kubectl run --generator=cronjob/v1beta1
-
컨테이너 확인
$ kubectl get pods $ kubectl get rc
$ kubectl get pods NAME READY STATUS RESTARTS AGE goapp-project-bcv5q 1/1 Running 0 2m26s $ kubectl get rc NAME DESIRED CURRENT READY AGE goapp-project 1 1 1 8m58s
아래 명령어를 추가적으로 수행해 보세요
kubectl get pods -o wide kubectl describe pod goapp-project-bcv5q
-
k8s 서비스 생성
$ kubectl expose rc goapp-project --type=LoadBalancer --name goapp-http
service/firstapp-http exposed
-
생성한 서비스 조회
$ kubectl get services
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE goapp-http LoadBalancer 10.96.225.172 <pending> 8080:31585/TCP 104s kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 14d
-
서비스 테스트 (여러번 수행)
curl http://10.96.225.172:8080
[출력]
hostname: goapp-project-bcv5q hostname: goapp-project-bcv5q hostname: goapp-project-bcv5q hostname: goapp-project-bcv5q
-
replication controller 를 통한 scale-out 수행
kubectl scale rc goapp-project --replicas=3
[출력]
replicationcontroller/goapp-project scaled
-
Scale-Out 결과 확인
kubectl get pod
[출력]
NAME READY STATUS RESTARTS AGE goapp-project-bcv5q 1/1 Running 0 16m goapp-project-c8hml 1/1 Running 0 26s goapp-project-r7kx5 1/1 Running 0 26s
-
서비스 테스트 (여러번 수행)
curl http://10.96.225.172:8080
[출력]
NAME READY STATUS RESTARTS AGE goapp-project-bcv5q 1/1 Running 0 16m goapp-project-c8hml 1/1 Running 0 26s goapp-project-r7kx5 1/1 Running 0 26s
-
POD 삭제
Replication Controller 를 통해 생성된 POD 는 개별 POD 가 삭제 되지 않습니다. Replication Controller 자체를 삭제 해야 합니다.
kubectl delete rc goapp-project
5. PODS
5.1 POD 기본
5.1 POD 설정을 yaml 파일로 가져오기
kubectl get pod goapp-project-bcv5q -o yaml
kubectl get po goapp-project-bcv5q -o json
크게 metadata, spec, status 항목으로 나누어 집니다.
[출력 - yaml]
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: "2020-01-10T07:37:49Z"
generateName: goapp-project-
labels:
run: goapp-project
name: goapp-project-bcv5q
namespace: default
ownerReferences:
- apiVersion: v1
blockOwnerDeletion: true
controller: true
kind: ReplicationController
name: goapp-project
uid: e223237f-17e2-44f4-aaee-07e8ff4592b2
resourceVersion: "3082141"
selfLink: /api/v1/namespaces/default/pods/goapp-project-bcv5q
uid: 72bebcbd-8e6e-4906-9f66-1c3821fa49ec
spec:
containers:
- image: dangtong/goapp
imagePullPolicy: Always
name: goapp-project
ports:
- containerPort: 8080
protocol: TCP
resources: {}
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
volumeMounts:
- mountPath: /var/run/secrets/kubernetes.io/serviceaccount
name: default-token-qz4fh
readOnly: true
dnsPolicy: ClusterFirst
enableServiceLinks: true
nodeName: worker01.sas.com
priority: 0
restartPolicy: Always
schedulerName: default-scheduler
securityContext: {}
serviceAccount: default
serviceAccountName: default
terminationGracePeriodSeconds: 30
tolerations:
- effect: NoExecute
key: node.kubernetes.io/not-ready
operator: Exists
tolerationSeconds: 300
- effect: NoExecute
key: node.kubernetes.io/unreachable
operator: Exists
tolerationSeconds: 300
volumes:
- name: default-token-qz4fh
secret:
defaultMode: 420
secretName: default-token-qz4fh
status:
conditions:
- lastProbeTime: null
lastTransitionTime: "2020-01-10T07:37:49Z"
status: "True"
type: Initialized
- lastProbeTime: null
lastTransitionTime: "2020-01-10T07:37:55Z"
status: "True"
type: Ready
- lastProbeTime: null
lastTransitionTime: "2020-01-10T07:37:55Z"
status: "True"
type: ContainersReady
- lastProbeTime: null
lastTransitionTime: "2020-01-10T07:37:49Z"
status: "True"
type: PodScheduled
containerStatuses:
- containerID: docker://de3418e51fea7f7a19e7b1d6ff5a4a6f386f337578838e6f1ec0589275ca6f48
image: dangtong/goapp:latest
imageID: docker-pullable://dangtong/goapp@sha256:e5872256539152aecd2a8fb1f079e132a6a8f247c7a2295f0946ce2005e36d05
lastState: {}
name: goapp-project
ready: true
restartCount: 0
started: true
state:
running:
startedAt: "2020-01-10T07:37:55Z"
hostIP: 192.168.56.103
phase: Running
podIP: 10.40.0.2
podIPs:
- ip: 10.40.0.2
qosClass: BestEffort
startTime: "2020-01-10T07:37:49Z"
###5.2 POD 생성을 위한 YAML 파일 만들기
아래와 같이 goapp.yaml 파일을 만듭니다.
apiVersion: v1
kind: Pod
metadata:
name: goapp-pod
spec:
containers:
- image: dangtong/goapp
name: goapp-container
ports:
- containerPort: 8080
protocol: TCP
ports 정보를 yaml 파일에 기록 하지 않으면 아래 명령어로 향후에 포트를 할당해도 됩니다.
kubectl port-forward goapp-pod 8080:8080
5.3 YAML 파일을 이용한 POD 생성 및 확인
$ kubectl create -f goapp.yaml
[output]
pod/goapp-pod created
$ kubectl get pod
[output]
NAME READY STATUS RESTARTS AGE
goapp-pod 1/1 Running 0 12m
goapp-project-bcv5q 1/1 Running 0 41m
goapp-project-c8hml 1/1 Running 0 25m
goapp-project-r7kx5 1/1 Running 0 25m
5.4 POD 및 Container 로그 확인
- POD 로그 확인
kubectl logs goapp-pod
[output]
Starting GoApp Server......
- Container 로그 확인
kubectl logs goapp-pod -c goapp-container
[output]
Starting GoApp Server......
현재 1개 POD 내에 Container 가 1이기 때문에 출력 결과는 동일 합니다. POD 내의 Container 가 여러개 일 경우 모든 컨테이너의 표준 출력이 화면에 출력됩니다.
[Exercise #2]
- Yaml 파일로 nginx 11.1 버전기반의 이미지를 사용해 nginx-app 이라는 이름의 Pod 를 만드세요(port : 8080)
- curl 명령어르 사용해. Nginx 서비스에 접속
- nginx Pod 의 정보를 yaml 파일로 출력 하세요
- nginx-app Pod 를 삭제 하세요
6. Lable
6.1 Lable 정보를 추가해서 POD 생성하기
- goapp-with-lable.yaml 이라 파일에 아래 내용을 추가 하여 작성 합니다.
apiVersion: v1
kind: Pod
metadata:
name: goapp-pod2
labels:
env: prod
spec:
containers:
- image: dangtong/goapp
name: goapp-container
ports:
- containerPort: 8080
protocol: TCP
- yaml 파일을 이용해 pod 를 생성 합니다.
$ kubectl create -f ./goapp-with-lable.yaml
[output]
pod/goapp-pod2 created
- 생성된 POD를 조회 합니다.
kubectl get po --show-labels
[output]
NAME READY STATUS RESTARTS AGE LABELS
goapp-pod 1/1 Running 0 160m <none>
goapp-pod2 1/1 Running 0 3m53s env=prod
goapp-project-bcv5q 1/1 Running 0 9h run=goapp-project
goapp-project-c8hml 1/1 Running 0 9h run=goapp-project
goapp-project-r7kx5 1/1 Running 0 9h run=goapp-project
- Lable 태그를 출력 화면에 컬럼을 분리해서 출력
kubectl get pod -L env
[output]
NAME READY STATUS RESTARTS AGE ENV
goapp-pod 1/1 Running 0 161m
goapp-pod2 1/1 Running 0 5m19s prod
goapp-project-bcv5q 1/1 Running 0 9h
goapp-project-c8hml 1/1 Running 0 9h
goapp-project-r7kx5 1/1 Running 0 9h
- Lable을 이용한 필터링 조회
kubectl get pod -l env=prod
[output]
NAME READY STATUS RESTARTS AGE
goapp-pod2 1/1 Running 0 39h
- Label 추가 하기
kubectl label pod goapp-pod2 app="application" tier="frondEnd"
- Label 삭제 하기
kubectl label pod goapp-pod2 app- tier-
6.2 Label 셀렉터 사용
- AND 연산
kubectl get po -l 'app in (application), tier in (frontEnd)'
- OR 연산
kubectl get po -l 'app in (application,backEnd)'
kubectl get po -l 'app in (application,frontEnd)'
6.3 생성된 POD 로 부터 yaml 파일 얻기
kubectl get pod goapp-pod -o yaml
[output]
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: "2020-01-10T08:07:04Z"
name: goapp-pod
namespace: default
resourceVersion: "3086366"
selfLink: /api/v1/namespaces/default/pods/goapp-pod
uid: 18cf0ed0-be56-4b54-869c-4473117800b1
spec:
containers:
- image: dangtong/goapp
imagePullPolicy: Always
name: goapp-container
ports:
- containerPort: 8080
protocol: TCP
resources: {}
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
volumeMounts:
- mountPath: /var/run/secrets/kubernetes.io/serviceaccount
name: default-token-qz4fh
readOnly: true
dnsPolicy: ClusterFirst
enableServiceLinks: true
nodeName: worker02.sas.com
priority: 0
restartPolicy: Always
schedulerName: default-scheduler
securityContext: {}
serviceAccount: default
serviceAccountName: default
terminationGracePeriodSeconds: 30
tolerations:
- effect: NoExecute
key: node.kubernetes.io/not-ready
operator: Exists
tolerationSeconds: 300
- effect: NoExecute
key: node.kubernetes.io/unreachable
operator: Exists
tolerationSeconds: 300
volumes:
- name: default-token-qz4fh
secret:
defaultMode: 420
secretName: default-token-qz4fh
status:
conditions:
- lastProbeTime: null
lastTransitionTime: "2020-01-10T08:07:04Z"
status: "True"
type: Initialized
- lastProbeTime: null
lastTransitionTime: "2020-01-10T08:07:09Z"
status: "True"
type: Ready
- lastProbeTime: null
lastTransitionTime: "2020-01-10T08:07:09Z"
status: "True"
type: ContainersReady
- lastProbeTime: null
lastTransitionTime: "2020-01-10T08:07:04Z"
status: "True"
type: PodScheduled
containerStatuses:
- containerID: docker://d76af359c556c60d3ac1957d7498513f42ace14998c763456190274a3e4a1d5e
image: dangtong/goapp:latest
imageID: docker-pullable://dangtong/goapp@sha256:e5872256539152aecd2a8fb1f079e132a6a8f247c7a2295f0946ce2005e36d05
lastState: {}
name: goapp-container
ready: true
restartCount: 0
started: true
state:
running:
startedAt: "2020-01-10T08:07:08Z"
hostIP: 10.0.2.5
phase: Running
podIP: 10.32.0.4
podIPs:
- ip: 10.32.0.4
qosClass: BestEffort
startTime: "2020-01-10T08:07:04Z"
6.4 Lable을 이용한 POD 스케줄링
- 노드목록 조회
kubectl get nodes
[output]
NAME STATUS ROLES AGE VERSION
master.sas.com Ready master 16d v1.17.0
worker01.sas.com Ready <none> 16d v1.17.0
worker02.sas.com Ready <none> 16d v1.17.0
- 특정 노드에 레이블 부여
kubectl label node worker02.sas.com memsize=high
- 레이블 조회 필터 사용하여 조회
kubectl get nodes -l memsize=high
[output]
NAME STATUS ROLES AGE VERSION
worker02.sas.com Ready <none> 17d v1.17.0
-
특정 노드에 신규 POD 스케줄링
아래 내용과 같이 goapp-label-node.yaml 파을을 작성 합니다.
apiVersion: v1
kind: Pod
metadata:
name: goapp-pod-memhigh
spec:
nodeSelector:
memsize: "high"
containers:
- image: dangtong/goapp
name: goapp-container-memhigh
- YAML 파일을 이용한 POD 스케줄링
kubectl create -f ./goapp-lable-node.yaml
[output]
pod/goapp-pod-memhigh created
- 생성된 노드 조회
kubectl get pod -o wide
[output]
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
goapp-pod-memhigh 1/1 Running 0 17s 10.32.0.5 worker02.sas.com <none> <none>
7. Annotation
7.1 POD 에 Annotation 추가하기
kubectl annotate pod goapp-pod-memhigh maker="dangtong" team="k8s-team"
[output]
pod/goapp-pod-memhigh annotated
7.2 Annotation 확인하기
- YAML 파일을 통해 확인하기
kubectl get po goapp-pod-memhigh -o yaml
[output]
kind: Pod
metadata:
annotations:
maker: dangtong
team: k8s-team
creationTimestamp: "2020-01-12T15:25:05Z"
name: goapp-pod-memhigh
namespace: default
resourceVersion: "3562877"
selfLink: /api/v1/namespaces/default/pods/goapp-pod-memhigh
uid: a12c35d7-d0e6-4c01-b607-cccd267e39ec
spec:
containers:
- DESCRIBE 를 통해 확인하기
kubectl describe pod goapp-pod-memhigh
[output]
Name: goapp-pod-memhigh
Namespace: default
Priority: 0
Node: worker02.sas.com/10.0.2.5
Start Time: Mon, 13 Jan 2020 00:25:05 +0900
Labels: <none>
Annotations: maker: dangtong
team: k8s-team
Status: Running
IP: 10.32.0.5
7.3 Annotation 삭제
kubectl annotate pod goapp-pod-memhigh maker- team-
[[Exercise #3]]
- bitnami/apache 이미지로 Pod 를 만들고 tier=FronEnd, app=apache 라벨 정보를 포함하세요
- Pod 정보를 출력 할때 라벨을 함께 출력 하세요
- app=apache 라벨틀 가진 Pod 만 조회 하세요
- 만들어진 Pod에 env=dev 라는 라벨 정보를 추가 하세요
- created_by=kevin 이라는 Annotation을 추가 하세요
- apache Pod를 삭제 하세요
8. Namespace
8.1 네임스페이스 조회
kubectl get namespace
kubectl get ns 와 동일함
[output]
NAME STATUS AGE
default Active 17d
kube-node-lease Active 17d
kube-public Active 17d
kube-system Active 17d
8.2 특정 네임스페이스의 POD 조회
kubectl get pod --namespace kube-system
# kubectl get po -n kube-system
kubectl get pod -n kube-system 과 동일함
[output]
coredns-6955765f44-glcdc 1/1 Running 0 17d
coredns-6955765f44-h7fbb 1/1 Running 0 17d
etcd-master.sas.com 1/1 Running 1 17d
kube-apiserver-master.sas.com 1/1 Running 1 17d
kube-controller-manager-master.sas.com 1/1 Running 1 17d
kube-proxy-gm44f 1/1 Running 1 17d
kube-proxy-ngqr6 1/1 Running 0 17d
kube-proxy-wmq7d 1/1 Running 0 17d
kube-scheduler-master.sas.com 1/1 Running 1 17d
weave-net-2pm2x 2/2 Running 0 17d
weave-net-4wksv 2/2 Running 0 17d
weave-net-7j7mn 2/2 Running 0 17d
###8.3 YAML 파일을 이용한 네임스페이스 생성
- YAML 파일 작성 : first-namespace.yaml 이름으로 파일 작성
apiVersion: v1
kind: Namespace
metadata:
name: first-namespace
- YAML 파일을 이용한 네이스페이스 생성
kubectl create -f first-namespace.yaml
[output]
namespace/first-namespace created
- 생성된 네임스페이스 확인
kubectl get namespace
kubectl get ns
[output]
NAME STATUS AGE
default Active 17d
first-namespace Active 5s
kube-node-lease Active 17d
kube-public Active 17d
kube-system Active 17d
kubectl create namespace first-namespace 와 동일 합니다.
8.4 특정 네임스페이스에 POD 생성
- first-namespace 에 goapp 생성
kubectl create -f goapp.yaml -n first-namespace
[output]
pod/goapp-pod created
- 생성된 POD 확인하기
kubectl get pod -n first-namespace
[output]
NAME READY STATUS RESTARTS AGE
goapp-pod 1/1 Running 0 12h
###8.5 POD 삭제
'kubectl' delete pod goapp-pod-memhigh
kubectl delete pod goapp-pod
kubectl delete pod goapp-pod -n first-namespace
현재 네임스페이스 에서 존재 하는 모든 리소스를 삭제하는 명령은 아래와 같습니다.
kubectl delete all –all
현재 네임스페이스를 설정하고 조회 하는 명령은 아래와 같습니다.
# 네임스페이스 설정 kubectl config set-context --current --namespace=<insert-namespace-name-here> # 확인 kubectl config view --minify | grep namespace:
[[Exercise #4]]
-
쿠버네티스 클러스터에 몇개의 네임스페이가 존재 하나요?
-
my-dev 라는 네임스페이를 생성하고 nginx Pod를 배포 하세요
9. kubectl 기본 사용법
9.1 단축형 키워드 사용하기
kubectl get po # PODs
kubectl get svc # Service
kubectl get rc # Replication Controller
kubectl get deploy # Deployment
kubectl get ns # Namespace
kubectl get no # Node
kubectl get cm # Configmap
kubectl get pv # PersistentVolumns
9.2 도움말 보기
kubectl -h
kubectl controls the Kubernetes cluster manager.
Find more information at: https://kubernetes.io/docs/reference/kubectl/overview/
Basic Commands (Beginner):
create Create a resource from a file or from stdin.
expose Take a replication controller, service, deployment or pod and expose it as a new Kubernetes Service
run Run a particular image on the cluster
set Set specific features on objects
Basic Commands (Intermediate):
explain Documentation of resources
get Display one or many resources
edit Edit a resource on the server
delete Delete resources by filenames, stdin, resources and names, or by resources and label selector
Deploy Commands:
kubectl get -h
Display one or many resources
Prints a table of the most important information about the specified resources. You can filter the list using a label
selector and the --selector flag. If the desired resource type is namespaced you will only see results in your current
namespace unless you pass --all-namespaces.
Uninitialized objects are not shown unless --include-uninitialized is passed.
By specifying the output as 'template' and providing a Go template as the value of the --template flag, you can filter
the attributes of the fetched resources.
Use "kubectl api-resources" for a complete list of supported resources.
Examples:
# List all pods in ps output format.
kubectl get pods
# List all pods in ps output format with more information (such as node name).
kubectl get pods -o wide
9.3 리소스 정의에 대한 도움말
kubectl explain pods
KIND: Pod
VERSION: v1
DESCRIPTION:
Pod is a collection of containers that can run on a host. This resource is
created by clients and scheduled onto hosts.
FIELDS:
apiVersion <string>
APIVersion defines the versioned schema of this representation of an
object. Servers should convert recognized schemas to the latest internal
value, and may reject unrecognized values. More info:
https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
kind <string>
Kind is a string value representing the REST resource this object
represents. Servers may infer this from the endpoint the client submits
requests to. Cannot be updated. In CamelCase. More info:
https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
metadata <Object>
Standard object's metadata. More info:
https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
spec <Object>
Specification of the desired behavior of the pod. More info:
https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status
status <Object>
Most recently observed status of the pod. This data may not be up to date.
Populated by the system. Read-only. More info:
https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status
9.4 리소스 감시하기
- Kube-system 네임스페이스에 있는 모든 pod에 대해 모니터링 합니다.
kubectl get pods --watch -n kube-system
root@master:~# k get pods --watch -n kube-system
NAME READY STATUS RESTARTS AGE
coredns-6955765f44-glcdc 1/1 Running 0 19d
coredns-6955765f44-h7fbb 1/1 Running 0 19d
etcd-master.sas.com 1/1 Running 1 19d
kube-apiserver-master.sas.com 1/1 Running 1 19d
kube-controller-manager-master.sas.com 1/1 Running 1 19d
kube-proxy-gm44f 1/1 Running 1 19d
kube-proxy-ngqr6 1/1 Running 0 19d
kube-proxy-wmq7d 1/1 Running 0 19d
kube-scheduler-master.sas.com 1/1 Running 1 19d
weave-net-2pm2x 2/2 Running 0 19d
weave-net-4wksv 2/2 Running 0 19d
weave-net-7j7mn 2/2 Running 0 19d
...
9.5 리소스 비교하기
kubectl diff -f goapp.yaml
9.6 kubectx 및 kubens 사용하기
현재 컨텍스트 및 네임스페이스를 확인하고 전환 할때 손쉽게 사용 할수 있는 도구
9.6.1 kubectx 및 kubens 설치
git clone https://github.com/ahmetb/kubectx.git ~/.kubectx
COMPDIR=$(pkg-config --variable=completionsdir bash-completion)
ln -sf ~/.kubectx/completion/kubens.bash $COMPDIR/kubens
ln -sf ~/.kubectx/completion/kubectx.bash $COMPDIR/kubectx
cat << FOE >> ~/.bashrc
#kubectx and kubens
export PATH=~/.kubectx:\$PATH
FOE
9.6.2 kubectx 및 kubens 사용
- kubectx 사용
kubectx
kubectx <변경하고 싶은 컨텍스트 이름>
- kubens 사용
현재 사용중인 네임스페이스를 조회 합니다. 현재 사용중인 네이스페이스는 하이라이트 됩니다.
kubens
default
first-namespace
kube-node-lease
kube-public
kube-system
Kube-system 네이스페이스로 전환 해봅니다.
kubens kube-system
Context "kubernetes-admin@kubernetes" modified.
Active namespace is "kube-system".
pod 조회 명령을 내리면 아래와 같이 kube-system 네임스페이스의 pod 들이 조회 됩니다.
kubectl get po
NAME READY STATUS RESTARTS AGE
coredns-6955765f44-glcdc 1/1 Running 0 34d
coredns-6955765f44-h7fbb 1/1 Running 0 34d
etcd-master.sas.com 1/1 Running 1 34d
kube-apiserver-master.sas.com 1/1 Running 1 34d
kube-controller-manager-master.sas.com 1/1 Running 1 34d
kube-proxy-gm44f 1/1 Running 1 34d
kube-proxy-ngqr6 1/1 Running 0 34d
kube-proxy-wmq7d 1/1 Running 0 34d
kube-scheduler-master.sas.com 1/1 Running 1 34d
weave-net-2pm2x 2/2 Running 0 34d
weave-net-4wksv 2/2 Running 0 34d
weave-net-7j7mn 2/2 Running 0 34d
9.7 kubernetes 컨텍스트 및 네임스페이스 표시하기
kube-ps1을 다운로드 하여 /usr/local/kube-ps1 설치 하고 .bashrc 파일에 아래와 같이 설정 합니다. 링크
source /usr/local/kube-ps1/kube-ps1.sh
PS1='[\u@\h \W $(kube_ps1)]\$ '
[root@master ~ (⎈ |kubernetes-admin@kubernetes:kube-public)]#
10. Liveness probes
liveness prove는 Pod에 지정된 주소에 Health Check 를 수행하고 실패할 경우 Pod를 다시 시작 합니다.
이때 중요한 점은 단순히 다시 시작만 하는 것이 아니라, 리포지토리로 부터 이미지를 다시 받아 Pod 를 다시 시작 합니다.
아래 내용으로.
apiVersion: v1
kind: Pod
metadata:
labels:
test: liveness
name: liveness-http
spec:
containers:
- name: liveness
image: k8s.gcr.io/liveness
args:
- /server
livenessProbe:
httpGet:
path: /healthz
port: 8080
httpHeaders:
- name: Custom-Header
value: Awesome
initialDelaySeconds: 3
periodSeconds: 3
K8s.gcr.io/liveness 이미지는 liveness 테스트를 위해 만들어진 이미지 입니다. Go 언어로 작성 되었으며, 처음 10초 동안은 정상적인 서비스를 하지만, 10초 후에는 에러를 발생 시킵니다. 자세한 사항은 URL 을 참고 하세요
10.1 Pod 생성
kubectl create -f ./liveness-probe-pod.yaml
###10.2 Pod 확인
kubectl get pod
아래
NAME READY STATUS RESTARTS AGE
liveness-http 1/1 Running 0 5s
NAME READY STATUS RESTARTS AGE
liveness-http 1/1 Running 1 26s
NAME READY STATUS RESTARTS AGE
liveness-http 1/1 Running 3 68s
NAME READY STATUS RESTARTS AGE
liveness-http 0/1 CrashLoopBackOff 3 81s
NAME READY STATUS RESTARTS AGE
liveness-http 0/1 CrashLoopBackOff 5 2m50s
10.3 Pod 로그 이벤트 확인
kubectl describe pod liveness-http
Name: liveness-http
Namespace: default
Priority: 0
Node: worker02.acorn.com/192.168.56.110
Start Time: Wed, 01 Apr 2020 05:54:29 +0000
Labels: test=liveness
Annotations: <none>
Status: Running
IP: 10.36.0.1
IPs:
IP: 10.36.0.1
Containers:
liveness:
Container ID: docker://0f1ba830b830d5879fe99776cd0db5f3678bf52a11e3ccb1a1e9c65460957817
Image: k8s.gcr.io/liveness
Image ID: docker-pullable://k8s.gcr.io/liveness@sha256:1aef943db82cf1370d0504a51061fb082b4d351171b304ad194f6297c0bb726a
Port: <none>
Host Port: <none>
Args:
/server
State: Running
Started: Wed, 01 Apr 2020 06:01:15 +0000
Last State: Terminated
Reason: Error
Exit Code: 2
Started: Wed, 01 Apr 2020 05:58:16 +0000
Finished: Wed, 01 Apr 2020 05:58:32 +0000
Ready: True
Restart Count: 7
Liveness: http-get http://:8080/healthz delay=3s timeout=1s period=3s #success=1 #failure=3
Environment: <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from default-token-zshgs (ro)
Conditions:
Type Status
Initialized True
Ready True
ContainersReady True
PodScheduled True
Volumes:
default-token-zshgs:
Type: Secret (a volume populated by a Secret)
SecretName: default-token-zshgs
Optional: false
QoS Class: BestEffort
Node-Selectors: <none>
Tolerations: node.kubernetes.io/not-ready:NoExecute for 300s
node.kubernetes.io/unreachable:NoExecute for 300s
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled <unknown> default-scheduler Successfully assigned default/liveness-http to worker02.acorn.com
Normal Pulled 6m14s (x3 over 6m53s) kubelet, worker02.acorn.com Successfully pulled image "k8s.gcr.io/liveness"
Normal Created 6m14s (x3 over 6m52s) kubelet, worker02.acorn.com Created container liveness
Normal Started 6m14s (x3 over 6m52s) kubelet, worker02.acorn.com Started container liveness
Normal Pulling 5m55s (x4 over 6m54s) kubelet, worker02.acorn.com Pulling image "k8s.gcr.io/liveness"
Warning Unhealthy 5m55s (x9 over 6m40s) kubelet, worker02.acorn.com Liveness probe failed: HTTP probe failed with statuscode: 500
Normal Killing 5m55s (x3 over 6m34s) kubelet, worker02.acorn.com Container liveness failed liveness probe, will be restarted
Warning BackOff 108s (x17 over 5m36s) kubelet, worker02.acorn.com Back-off restarting failed container
로그이벤트를 보면 Liveness Probe 가 실패해서 컨테이너를 재가동 하는 메시지가 보입니다.
뿐만아니라, 재가동 시에서 Pull image 를 통해 이미지를 다시 가져 와서 재가동 시키는 것을 볼 수 있습니다.
11. Replication Controller
11.1 Replication Controller 생성
아래와 같이 template를 작성합니다.
apiVersion: v1
kind: ReplicationController
metadata:
name: goapp-rc
spec:
replicas: 3
selector:
app: goapp
template:
metadata:
name: goapp-pod
labels:
tier: forntend
app: goapp
env: prod
priority: high
spec:
containers:
- name: goapp-container
image: dangtong/goapp
ports:
- containerPort: 8080
11.2 Pod 생성
kubectl create -f ./rc-goapp.yaml
11.3 Pod 생성 확인
kubectl get po
NAME READY STATUS RESTARTS AGE
goapp-rc-9q689 1/1 Running 0 39s
goapp-rc-d5rnf 1/1 Running 0 39s
goapp-rc-fm7kr 1/1 Running 0 39s
11.4 Replication Controller 확인
kubectl get rc
NAME DESIRED CURRENT READY AGE
goapp-rc 3 3 3 58s
kubectl get rc -o wide
NAME DESIRED CURRENT READY AGE CONTAINERS IMAGES SELECTOR
goapp-rc 3 3 3 72s goapp-container dangtong/goapp app=goapp
11.5 특정 Pod 삭제하고 변화 확인하기
아래와 같이 3개의 Pod 중에 하나를 선택해서 삭제 합니다.
kubectl deleete pod goapp-rc-9q689
kubectl get pod
NAME READY STATUS RESTARTS AGE
goapp-rc-d5rnf 1/1 Running 0 2m
goapp-rc-fm7kr 1/1 Running 0 2m
goapp-rc-szv2r 1/1 ContainerCreating 0 6s
기존 컨테이너를 Terminating 하고 새로운 컨테이너를 생성하는 것을 볼 수 있습니다.
11.6 Pod 정보를 라벨과 함께 출력해보기
kubectl get pod --show-labels
NAME READY STATUS RESTARTS AGE LABELS
goapp-rc-d5rnf 1/1 Running 0 7m26s app=goapp
goapp-rc-fm7kr 1/1 Running 0 7m26s app=goapp
goapp-rc-szv2r 1/1 Running 0 4m51s app=goapp
11.7 Pod 라벨을 변경해보기
기존 "app=nginx" 라는 label 을 "app=goapp-exit" 로 변경 합니다.
kubectl label pod goapp-rc-szv2r app=goapp-exit --overwrite
아래와 같이 pod 를 조회 해봅니다.
kubectl get po
NAME READY STATUS RESTARTS AGE
goapp-rc-d5rnf 1/1 Running 0 8m49s
goapp-rc-fm7kr 1/1 Running 0 8m49s
goapp-rc-mmn2b 0/1 ContainerCreating 0 5s
goapp-rc-szv2r 1/1 Running 0 6m14s
기존 3개의 Pod 중 하나의 Label을 변경하면 기존 app=goapp 에는 2개의 Pod 만 남기 때문에 Replication Controller 는 추가적으로 하나의 Pod 를 생성 합니다.
NAME READY STATUS RESTARTS AGE LABELS
goapp-rc-d5rnf 1/1 Running 0 9m27s app=goapp
goapp-rc-fm7kr 1/1 Running 0 9m27s app=goapp
goapp-rc-mmn2b 1/1 Running 0 43s app=goapp
goapp-rc-szv2r 1/1 Running 0 6m52s app=goapp-exit
11.8 Pod Template 변경 해보기
아래와 같이 Pod Template의 spec ➢ spec ➢ containers ➢ image 항목을 dangtong/goapp-v2 로 변경 합니다.
kubectl edit rc nginx
# 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: ReplicationController
metadata:
creationTimestamp: "2020-04-01T09:32:23Z"
generation: 1
labels:
app: goapp
name: goapp-rc
namespace: default
resourceVersion: "405444"
selfLink: /api/v1/namespaces/default/replicationcontrollers/goapp-rc
uid: 17198300-d964-4de6-a160-825a7a9c16bf
spec:
replicas: 3
selector:
app: goapp
template:
metadata:
creationTimestamp: null
labels:
app: goapp
name: goapp-pod
spec:
containers:
- image: dangtong/goapp-v2 # 이부분을 변경 합닏다.(기존 : dangtong/goapp)
imagePullPolicy: Always
name: goapp-container
ports:
- containerPort: 80
protocol: TCP
resources: {}
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
dnsPolicy: ClusterFirst
restartPolicy: Always
schedulerName: default-scheduler
securityContext: {}
terminationGracePeriodSeconds: 30
status:
availableReplicas: 3
fullyLabeledReplicas: 3
observedGeneration: 1
readyReplicas: 3
replicas: 3
저장후 편집기를 종료 합니다.
리눅스 편집기에는 다양한 종유가 있습니다. 만약 기본 편집기를 변경하고 싶으면
KUBE_EDITOR="/bin/nano" 를 $HOME/.bashrc 파일에 선언 해주면 원하는 편집기를 사용 할수 있습니다.
###11.9 Pod Template 를 적용하기 위해 임의의 Pod 삭제하기
kubectl get pod
goapp-rc-mvw57 1/1 Running 0 3h6m 10.36.0.2 worker02.acorn.com
goapp-rc-qkrpw 1/1 Running 0 6m26s 10.32.0.2 worker01.acorn.com
goapp-rc-x6q4d 1/1 Running 0 3h6m 10.36.0.1 worker02.acorn.com
Pod 삭제
kubectl delete pod goapp-rc-mvw57
pod "goapp-rc-mvw57" deleted
Pod 확인
kubectl get pod
NAME READY STATUS RESTARTS AGE
goapp-rc-bf2xk 0/1 ContainerCreating 0 8s
goapp-rc-qkrpw 1/1 Running 0 7m5s
goapp-rc-x6q4d 1/1 Running 0 3h7m
kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
goapp-rc-bf2xk 1/1 Running 0 21s 10.32.0.3 worker01.acorn.com
goapp-rc-qkrpw 1/1 Running 0 7m18s 10.32.0.2 worker01.acorn.com
goapp-rc-x6q4d 1/1 Running 0 3h7m 10.36.0.1 worker02.acorn.com
접속 해보기
# dangtong/goapp
curl http://10.32.0.2:8080
hostname: goapp-rc-qkrpw
# dangtong/goapp-v3
curl http://10.32.0.3:8080
hostname: goapp-rc-bf2xk
version: goapp-v2
###11.10 Pod 스케일링
-
Template 변경을 통한 스케일링
아래와 같이 goapp-rc 를 edit 명령으로 수정 합니다. (replicas 항목을 3에서 4로 수정)
정kubectl edit rc goapp-rc
# 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: ReplicationController
metadata:
creationTimestamp: "2020-04-01T09:51:49Z"
generation: 3
labels:
app: goapp
name: goapp-rc
namespace: default
resourceVersion: "416408"
selfLink: /api/v1/namespaces/default/replicationcontrollers/goapp-rc
uid: 23f58f51-88ab-4828-9a76-cde8a646fff4
spec:
replicas: 4 # 이부분을 변경 합니다. (기존 : 3)
selector:
app: goapp
template:
metadata:
creationTimestamp: null
labels:
app: goapp
name: goapp-pod
spec:
containers:
- image: dangtong/goapp-v2
imagePullPolicy: Always
name: goapp-container
ports:
저장 한다음 Pod 및 RC 확인
kubectl get pod
NAME READY STATUS RESTARTS AGE
goapp-rc-bf2xk 1/1 Running 0 19m
goapp-rc-mr6kb 0/1 ContainerCreating 0 7s
goapp-rc-qkrpw 1/1 Running 0 26m
goapp-rc-x6q4d 1/1 Running 0 3h26m
kubectl get rc
NAME DESIRED CURRENT READY AGE
goapp-rc 4 4 4 4h17m
- 명령어를 통한 스케일링
명령어를 이용해서 스케일링을 수행 할 수 있습니다.
kubectl scale rc goapp-rc --replicas=5
실제로 Pod 가 늘어 났는지 확인해봅니다.
kubectl get pod
NAME READY STATUS RESTARTS AGE
goapp-rc-bf2xk 1/1 Running 0 72m
goapp-rc-dlgfc 0/1 ContainerCreating 0 4s
goapp-rc-mr6kb 1/1 Running 0 53m
goapp-rc-qkrpw 1/1 Running 0 79m
goapp-rc-x6q4d 1/1 Running 0 4h19m
###11.11 Replication Controller 삭제
Replication Controller 와 POD 모두 삭제
kubectl delete rc goapp-rc
Replication Controller 만 삭제. POD 는 그대로 유지 합니다.
kubectl delete rc goapp-rc --cascade=false
12.ReplicaSet
12.1 RS 생성
Selector 를 작성 할때 ForntEnd 이고 운영계 이면서 중요도가 High 인 POD 에 대해 RS 를 생성 합니다.
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: frontend
labels:
app: guestbook
tier: frontend
spec:
replicas: 3
selector:
matchLabels:
tier: frontend
matchExpressions:
- {key: env, operator: In, values: [prod]}
- {key: priority, operator: NotIn, values: [low]}
template:
metadata:
labels:
tier: frontend
env: prod
priority: high
spec:
containers:
- name: php-redis
image: gcr.io/google_samples/gb-frontend:v3
12.2 RS 확인
$ kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE
frontend-bstms 1/1 Running 0 53s 10.32.2.7 gke-gke1-default-pool-ad44d907-cq8j
frontend-d4znb 1/1 Running 0 53s 10.32.2.9 gke-gke1-default-pool-ad44d907-cq8j
frontend-rv9bl 1/1 Running 0 53s 10.32.2.8 gke-gke1-default-pool-ad44d907-cq8j
$ kubectl get rs -o wide
AME READY STATUS RESTARTS AGE IP NODE
frontend-bstms 1/1 Running 0 68s 10.32.2.7 gke-gke1-default-pool-ad44d907-cq8j
frontend-d4znb 1/1 Running 0 68s 10.32.2.9 gke-gke1-default-pool-ad44d907-cq8j
frontend-rv9bl 1/1 Running 0 68s 10.32.2.8 gke-gke1-default-pool-ad44d907-cq8j
$ kubectl get pod --show-labels
NAME READY STATUS RESTARTS AGE LABELS
frontend-bstms 1/1 Running 0 107s env=prod,priority=high,tier=frontend
frontend-d4znb 1/1 Running 0 107s env=prod,priority=high,tier=frontend
frontend-rv9bl 1/1 Running 0 107s env=prod,priority=high,tier=frontend
[[Exercise #5]]
- Nginx Pod 3개로 구성된 Replication Controller를 작성 하세요
- Replication Controller 만 삭제 하세요(Pod 는 유지)
- 남겨진 Nginx Pod를 관리하는 ReplicaSet 을 작성하된 replica 4개로 구성 하시요
- Nginx Pod 를 6개로 Scale Out 하세요
13.DeamonSet
13.1 데몬셋 생성
goapp-ds.yaml 이라는 이름으로 아래 파일을 작성 합니다.
piVersion: apps/v1
kind: DaemonSet
metadata:
name: goapp-on-ssd
spec:
selector:
matchLabels:
app: goapp-pod
template:
metadata:
labels:
app: goapp-pod
spec:
nodeSelector:
disk: ssd
containers:
- name: goapp-container
image: dangtong/goapp
데몬셋을 생성 합니다.
$ kubectl create -f ./goapp-ds.yaml
Pod 와 데몬셋을 조회 합니다.
$ kubectl get pod
$ kubectl get ds
NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE
goapp-on-ssd 0 0 0 0 0 disk=ssd <nome>
조회 하면 Pod 도 존재하지 않고 데몬셋 정보를 조회 해도 모두 0 으로 나옵닏다. 노드에 disk=ssd 라벨이 없기 때문입니다.
이제 라벨을 추가 합니다.
$ kubectl label node worker01.acorn.com disk=ssd
$ kubectl get pod
NAME READY STATUS RESTARTS AGE
goapp-on-ssd-vwvks 1/1 Running 0 7s
$ kubectl label node worker02.acorn.com disk=ssd
$ kubectl get pod
NAME READY STATUS RESTARTS AGE
goapp-on-ssd-nbnwz 1/1 Running 0 7s
goapp-on-ssd-vwvks 1/1 Running 0 36s
$ kubectl get ds -o wide
AME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE
goapp-on-ssd 2 2 2 2 2 disk=ssd 10m
14.Deployment
14.1 Deployment 생성
아래와 같이 nginx 를 서비스 하고 replica 가 3개인 Deployment 를 작성합니다.(nginx-deploy.yaml)
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.7.9
ports:
- containerPort: 80
kubectl apply -f ./nginx-deploy.yaml
14.2 Deployment 확인
kubectl get pod,rs,deploy
NAME READY STATUS RESTARTS AGE
pod/nginx-deployment-54f57cf6bf-dpsn4 1/1 Running 0 30s
pod/nginx-deployment-54f57cf6bf-ghfwm 1/1 Running 0 30s
pod/nginx-deployment-54f57cf6bf-rswwk 1/1 Running 0 30s
NAME DESIRED CURRENT READY AGE
replicaset.apps/nginx-deployment-54f57cf6bf 3 3 3 30s
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/nginx-deployment 3/3 3 3 30s
14.3 이미지 업데이트
- 기본 방식
kubectl --record deployment.apps/nginx-deployment set image deployment.v1.apps/nginx-deployment nginx=nginx:1.9.1
- 단축 방식
kubectl set image deployment/nginx-deployment nginx=nginx:1.9.1 --record
- yaml 파일 수정(.spec.template.spec.containers[0].image 변경)
kubectl edit deployment.v1.apps/nginx-deployment
- 롤백
kubectl set image deployment.v1.apps/nginx-deployment nginx=nginx:1.7.9 --record=true
14.4 Deployment ScaleOut
kubectl edit deploy goapp-deployment
kubectl scale deploy nginx-deployment
goapp-deployment-5857594fbb-2hhnv 1/1 Running 0 32m
goapp-deployment-5857594fbb-6s9lx 1/1 Running 0 6s
goapp-deployment-5857594fbb-7nqsg 1/1 Running 0 32m
goapp-deployment-5857594fbb-9b28s 1/1 Running 0 32m
14.4 deployment 확인 하기
- 롤아웃 확인
kubectl rollout status deployment.v1.apps/nginx-deployment
- deployment 상세 확인
kubectl describe deploy nginx-deployment
[[Exercise #6]]
1.
5. 서비스 (Service)
5.1 ClusterIP
5.1.0 nodes app 생성
const http = require('http');
const os = require('os');
console.log("Kubia server starting...");
var handler = function(request, response) {
console.log("Received request from " + request.connection.remoteAddress);
response.writeHead(200);
response.end("You've hit " + os.hostname() + "\n");
};
var www = http.createServer(handler);
www.listen(8080);
5.1.1. pod 생성
apiVersion: apps/v1
kind: Deployment
metadata:
name: nodeapp-deploy
spec:
replicas: 3
selector:
matchLabels:
app: nodeapp-pod
template:
metadata:
labels:
app: nodeapp-pod
spec:
containers:
- name: nodeapp-container
image: dangtong/nodeapp
ports:
- containerPort: 8080
5.1.2 yaml을 통한 ClusterIP 생성
apiVersion: v1
kind: Service
metadata:
name: nodeapp-service
spec:
ports:
- port: 80
targetPort: 8080
selector:
app: nodeapp-pod
5.1.3 서비스 상태 확인
kubectl get po,deploy,svc
NAME READY STATUS RESTARTS AGE
pod/nodeapp-deployment-55688d9d4b-8pzsk 1/1 Running 0 2m45s
pod/nodeapp-deployment-55688d9d4b-pslvb 1/1 Running 0 2m46s
pod/nodeapp-deployment-55688d9d4b-whbk8 1/1 Running 0 2m46s
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/nodeapp-deployment 3/3 3 3 2m46s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
nodeapp-service ClusterIP 10.101.249.42 <none> 80/TCP 78s
5.1.4 서비스 확인
curl http://10.101.249.42 #여러번 수행 하기
You've hit nodeapp-deployment-55688d9d4b-8pzsk
5.1.5 원격 Pod에서 curl 명령 수행하기
kubectl exec nodeapp-deployment-55688d9d4b-8pzsk -- curl -s http://10.101.249.42
You've hit nodeapp-deployment-55688d9d4b-whbk8
.더블 대시는 kubectl 명령의의 종료를 가르킴
5.1.6 서비스 삭제
kubectl delete svc nodeapp-service
5.2 NodePort
5.2.1 yaml 을 이용한 NodePort 생성 (GCP 에서 수행 하기)
apiVersion: v1
kind: Service
metadata:
name: node-nodeport
spec:
type: NodePort
ports:
- port: 80
targetPort: 8080
nodePort: 30123
selector:
app: node
5.2.2 NodePort 조회
kubectl get po,rs,svc
NAME READY STATUS RESTARTS AGE
pod/nodeapp-deployment-55688d9d4b-8pzsk 1/1 Running 0 145m
pod/nodeapp-deployment-55688d9d4b-pslvb 1/1 Running 0 145m
pod/nodeapp-deployment-55688d9d4b-whbk8 1/1 Running 0 145m
NAME DESIRED CURRENT READY AGE
replicaset.apps/nodeapp-deployment-55688d9d4b 3 3 3 145m
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 10d
service/nodeapp-nodeport NodePort 10.108.30.68 <none> 80:30123/TCP 4m14s
5.2.3 NodePort 를 통한 서비스 접속 확인(여러번 수행)
$ curl http://localhost:30123
You've hit nodeapp-deployment-55688d9d4b-pslvb
$ curl http://localhost:30123
You've hit nodeapp-deployment-55688d9d4b-whbk8
$ curl http://localhost:30123
You've hit nodeapp-deployment-55688d9d4b-pslvb
5.2.4 NodePort 삭제
kubectl delete svc nodeapp-nodeport
5.3 LoadBalancer (GCP 에서 수행)
5.3.1 yaml 파일로 deployment 생성
apiVersion: apps/v1
kind: Deployment
metadata:
name: nodeapp-deployment
labels:
app: nodeapp
spec:
replicas: 3
selector:
matchLabels:
app: nodeapp-pod
template:
metadata:
labels:
app: nodeapp-pod
spec:
containers:
- name: nodeapp-container
image: dangtong/nodeapp
ports:
- containerPort: 8080
5.3.2 서비스 확인
$ kubectl get po,rs,deploy
NAME READY STATUS RESTARTS AGE
pod/nodeapp-deployment-7d58f5d487-7hphx 1/1 Running 0 20m
pod/nodeapp-deployment-7d58f5d487-d74rp 1/1 Running 0 20m
pod/nodeapp-deployment-7d58f5d487-r8hq8 1/1 Running 0 20m
NAME DESIRED CURRENT READY AGE
replicaset.extensions/nodeapp-deployment-7d58f5d487 3 3 3 20m
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.extensions/nodeapp-deployment 3/3 3 3 20m
kubectl get po -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nodeapp-deployment-7d58f5d487-7hphx 1/1 Running 0 21m 10.32.2.10 gke-gke1-default-pool-ad44d907-cq8j
nodeapp-deployment-7d58f5d487-d74rp 1/1 Running 0 21m 10.32.2.12 gke-gke1-default-pool-ad44d907-cq8j
nodeapp-deployment-7d58f5d487-r8hq8 1/1 Running 0 21m 10.32.2.11 gke-gke1-default-pool-ad44d907-cq8j
5.3.2 nodeapp 접속 해보기
$ kubectl exec nodeapp-deployment-7d58f5d487-7hphx -- curl -s http://10.32.2.10:8080
또는
$ kubectl exec -it nodeapp-deployment-7d58f5d487-7hphx bash
$ curl http://10.32.2.10:8080
You've hit nodeapp-deployment-7d58f5d487-7hphx
5.3.3 yaml 파일을 이용해 LoadBalancer 생성
apiVersion: v1
kind: Service
metadata:
name: nodeapp-lb
spec:
type: LoadBalancer
ports:
- port: 80
targetPort: 8080
selector:
app: nodeapp-pod
5.3.5 LoadBalancer 생성 확인
kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.36.0.1 <none> 443/TCP 7d21h
nodeapp-lb LoadBalancer 10.36.14.234 <pending> 80:31237/TCP 33s
현재 pending 상태임 20초 정도 지나면
kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.36.0.1 <none> 443/TCP 7d21h
nodeapp-lb LoadBalancer 10.36.14.234 35.221.179.171 80:31237/TCP 45s
5.3.6 서비스 확인
curl http://35.221.179.171
You've hit nodeapp-deployment-7d58f5d487-r8hq8
5.4 Ingress (GCP 에서 수행)
5.4.1 Deployment 생성
- nginx / goapp deployment 생성
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx-container
image: nginx:1.7.9
ports:
- containerPort: 80
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: goapp-deployment
labels:
app: goapp
spec:
replicas: 3
selector:
matchLabels:
app: goapp
template:
metadata:
labels:
app: goapp
spec:
containers:
- name: goapp-container
image: dangtong/goapp
ports:
- containerPort: 8080
5.4.2 Service 생성
apiVersion: v1
kind: Service
metadata:
name: nginx-lb
spec:
type: LoadBalancer
ports:
- port: 80
targetPort: 80
selector:
app: nginx
---
apiVersion: v1
kind: Service
metadata:
name: goapp-lb
spec:
type: LoadBalancer
ports:
- port: 80
targetPort: 8080
selector:
app: goapp
5.4.3 Ingress 생성
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: nginx-goapp-ingress
spec:
tls:
- hosts:
- nginx.acorn.com
- goapp.acorn.com
secretName: acorn-secret
rules:
- host: nginx.acorn.com
http:
paths:
- path: /
backend:
serviceName: nginx-lb
servicePort: 80
- host: goapp.acorn.com
http:
paths:
- path: /
backend:
serviceName: goapp-lb
servicePort: 80
5.4.4 Ingress 조회
kubectl get ingress
NAME HOSTS ADDRESS PORTS AGE
nginx-goapp-ingress nginx.acorn.com,goapp.acorn.com 80, 443 15s
Ingress 가 완전히 생성되기 까지 시간이 걸립니다. 2~5분 소요
다시 조회 합니다
kubectl get ingress
NAME HOSTS ADDRESS PORTS AGE
nginx-goapp-ingress nginx.acorn.com,goapp.acorn.com 35.227.227.127 80, 443 13m
5.4.5 /etc/hosts 파일 수정
sudo vi /etc/hosts
35.227.227.127 nginx.acorn.com goapp.acorn.com
5.4.6 서비스 확인
$ curl http://goapp.acorn.com
hostname: goapp-deployment-d7564689f-6rrzw
$ curl http://nginx.acorn.com
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
body {
width: 35em;
margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif;
}
</style>
</head>
<body>
5.4.7 HTTPS 서비스 (TLS OffLoad)
- 인증서 생성 및 인증서 secret 등록
openssl genrsa -out server.key 2048
openssl req -new -x509 -key server.key -out server.cert -days 360 -subj /CN=nginx.acorn.com
kubectl create secret tls acorn-secret --cert=server.cert --key=server.key
- 테스트
$ curl -k https://nginx.acorn.com
$ curl -k https://goapp.acorn.com
7.Volums
7.1 EmptyDir (GCP 에서 수행)
7.1.1 Docker 이미지 만들기
아래와 같이 폴더를 만들고 ./fortune/docimg 폴더로 이동합니다.
$ mkdir -p ./fortune/docimg
$ mkdir -p ./fortune/kubetmp
아래와 같이 docker 이미지를 작성하기 위해 bash 로 Application을 작성 합니다.
파일명 : fortuneloop.sh
#!/bin/bash
trap "exit" SIGINT
mkdir /var/htdocs
while :
do
echo $(date) Writing fortune to /var/htdocs/index.html
/usr/games/fortune > /var/htdocs/index.html
sleep 10
done
Dockerfile 을 작성 합니다.
FROM ubuntu:latest
RUN apt-get update; apt-get -y install fortune
ADD fortuneloop.sh /bin/fortuneloop.sh
ENTRYPOINT /bin/fortuneloop.sh
Dcoker 이미지를 만듭니다.
$ docker build -t dangtong/fortune .
Docker 이미지를 Docker Hub 에 push 합니다.
$ docker login
$ docker push dangtong/fortune
7.1.2 Deployment 작성
fortune APP을 적용하기 위해 Deployment 를 작성 합니다.
cd ../ktmp/
vi fortune-deploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: fortune-deployment
labels:
app: fortune
spec:
replicas: 3
selector:
matchLabels:
app: fortune
template:
metadata:
labels:
app: fortune
spec:
containers:
- image: dangtong/fortune
name: html-generator
volumeMounts:
- name: html
mountPath: /var/htdocs
- image: nginx:alpine
name: web-server
volumeMounts:
- name: html
mountPath: /usr/share/nginx/html
readOnly: true
ports:
- containerPort: 80
protocol: TCP
volumes:
- name: html
emptyDir: {}
html 볼륨을 html-generator 및 web-seerver 컨테이너에 모두 마운트 하였습니다.
html 볼륨에는 /var/htdocs 및 /usr/share/nginx/html 이름 으로 서로 따른 컨테이너에서 바라 보게 됩니다.
다만, web-server 컨테이너는 읽기 전용(reeadOnly) 으로만 접근 하도록 설정 하였습니다.
emptDir 을 디스크가 아닌 메모리에 생성 할 수도 있으며, 이를 위해서는 아래와 같이 설정을 바꾸어 주면 됩니다.
emptyDir:
medium: Memory
7.1.3 LoadBalancer 작성
vi fortune-lb.yaml
apiVersion: v1
kind: Service
metadata:
name: fortune-lb
spec:
selector:
app: fortune
ports:
- port: 80
targetPort: 80
type: LoadBalancer
externalIPs:
- 192.168.56.108
7.1.4 Deployment 및 Loadbalancer 생성
$ kubectl apply -f ./fortune-deploy.yaml
$ kubectl apply -f ./fortune-lb.yaml
7.1.5. 서비스 확인
curl http://192.168.56.108
7.2 Git EmptyDir
7.2.1 웹서비스용 Git 리포지토리 생성
Appendix3 . Git 계정 생성 및 Sync 참조
7.2.2 Deployment 용 yaml 파일 작성
$ cd ./gitvolume/kubetmp
$ vi gitvolume-deploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: gitvolume-deployment
labels:
app: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- image: nginx:alpine
name: web-server
volumeMounts:
- name: html
mountPath: /usr/share/nginx/html
readOnly: true
ports:
- containerPort: 80
protocol: TCP
volumes:
- name: html
gitRepo:
repository: https://github.com/dangtong76/k8s-web.git
revision: master
directory: .
7.2.3 Deployment 생성
$ kubectl apply -f ./gitvolume-deploy.yaml
7.3 GCE Persisteent DISK 사용하기
7.3.1. Persistent DISK 생성
- 리전/존 확인
$ gcloud container clusters list
- Disk 생성
$ gcloud compute disks create --size=16GiB --zone asia-northeast1-b mongodb
# 삭제
# gcloud compute disks delete mongodb --zone asia-northeast1-b
7.3.2 Pod 생성을 위한 yaml 파일 작성
- 파일명 : gce-pv.yaml
apiVersion: v1
kind: Pod
metadata:
name: mongodb
spec:
volumes:
- name: mongodb-data
gcePersistentDisk:
pdName: mongodb
fsType: ext4
containers:
- image: mongo
name: mongodb
volumeMounts:
- name: mongodb-data
mountPath: /data/db
ports:
- containerPort: 27017
protocol: TCP
- Pod 생성
$ kubectl apply -f ./gce-pv.yaml
$ kubectl get po
NAME READY STATUS RESTARTS AGE
mongodb 1/1 Running 0 8m42s
- Disk 확인
$ kubectl describe pod mongodb
...(중략)
Volumes:
mongodb-data:
Type: GCEPersistentDisk (a Persistent Disk resource in Google Compute Engine)
PDName: mongodb # 디스크이름
FSType: ext4
Partition: 0
ReadOnly: false
default-token-dgkd5:
Type: Secret (a volume populated by a Secret)
SecretName: default-token-dgkd5
Optional: false
...(중략)
7.3.3 Mongodb 접속 및 데이터 Insert
- 접속
kubectl exec -it mongodb mongo
- 데이터 Insert
> use mystore
> db.foo.insert({"first-name" : "dangtong"})
> db.foo.find()
{ "_id" : ObjectId("5f9c4127caf2e6464e18331c"), "first-name" : "dangtong" }
> exit
7.3.4 MongoDB Pod 재시작
- MongoDB 중단
$ kubectl delete pod mongodb
- MongoDB Pod 재생성
$ kubectl apply -f ./gce-pv.yaml
- 기존에 Insert 한 데이터 확인
$ kubectl exec -it mongodb mongo
> use mystore
> db.foo.find()
{ "_id" : ObjectId("5e9684134384860bc207b1f9"), "first-name" : "dangtong" }
7.3.5 Pod 삭제
$ kubectl delete po mongodb
7.4 PersistentVolume 및 PersistentVolumeClaim
7.4.1 PersistentVolume 생성
gce-pv2.yaml 로 작성
apiVersion: v1
kind: PersistentVolume
metadata:
name: mongodb-pv
spec:
capacity:
storage: 1Gi
accessModes:
- ReadWriteOnce
- ReadOnlyMany
persistentVolumeReclaimPolicy: Retain
gcePersistentDisk:
pdName: mongodb
fsType: ext4
kubectl apply -f ./gce-pv2.yaml
kubectl get pv
7.4.2 PersistentVolumeClaim 생성
gce-pvc.yaml 로 작성
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mongodb-pvc
spec:
resources:
request:
storage: 1Gi
accessModes:
- ReadWriteOnce
storageClassName: ""
kubectl apply -f ./gce-pvc.yaml
kubectl get pvc
7.4.3 PV, PVC 를 이용한 Pod 생성
gce-pod.yaml 파일 생성
apiVersion: v1
kind: Pod
metadata:
name: mongodb
spec:
containers:
- image: mongo
name: mongodb
volumeMounts:
- name: mongodb-data
mountPath: /data/db
- Ports:
- containerPort: 27017
protocol: TCP
volumes:
- name: mongodb-data
persistentVolumeClaim:
claimName: mongdodb-pvc
$ kubectl apply -f ./gce-pod.yaml
$ kubectl get po,pv,pvc
7.4.4 Mongodb 접속 및 데이터 확인
$ kubectl exec -it mongodb mongo
> use mystore
> db.foo.find()
7.5 Persistent Volume 의 동적 할당
7.5.1 StorageClass 를 이용해 스토리지 유형 정의
- gce-sclass.yaml
- 존환인 : gcloud container clusters list
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: fast
provisioner: kubernetes.io/gce-pd
parameters:
type: pd-ssd
zone: asia-northeast1-b #클러스터를 만든 지역으로 설정 해야함
$ kubectl apply -f ./gce-sclass.yaml
7.5.2 PVC 생성
- gce-pvc-sclass.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mongodb-pvc
spec:
storageClassName: fast
resources:
requests:
storage: 100Mi
accessModes:
- ReadWriteOnce
$ kubectl apply -f ./gce-pvc-sclass.yaml
7.5.3 PV 및 PVC 확인
- pvc 확인
$ kubectl get pvc mongdb-pvc
- pv 확인
$ kubectl get pv
7.5.4 PVC 를 이용한 POD 생성
파일명 : gce-pod.yaml 파일 생성
apiVersion: v1
kind: Pod
metadata:
name: mongodb
spec:
containers:
- image: mongo
name: mongodb
volumeMounts:
- name: mongodb-data
mountPath: /data/db
- Ports:
- containerPort: 27017
protocol: TCP
volumes:
- name: mongodb-data
persistentVolumeClaim:
claimName: mongdodb-pvc
8. ConfigMap
8.1 도커에서 매개변수 전달
8.1.1 디렉토리 생성 및 소스 코드 작성
mkdir -p ./configmap/docimg/indocker
mkdir -p ./configmap/kubetmp
cd ./configmap/docimg/indocker
vi fortuneloop.sh
#!/bin/bash
trap "exit" SIGINT
INTERVAL=$1
echo "Configured to generate neew fortune every " $INTERVAL " seconds"
mkdir /var/htdocs
while :
do
echo $(date) Writing fortune to /var/htdocs/index.html
/usr/games/fortune > /var/htdocs/index.html
sleep $INTERVAL
done
chmod 755 fortuneloop.sh
8.1.2 Docker 이미지 생성
$ vi dockerfile
FROM ubuntu:latest
RUN apt-get update; apt-get -y install fortune
ADD fortuneloop.sh /bin/fortuneloop.sh
ENTRYPOINT ["/bin/fortuneloop.sh"]
CMD ["10"] # args가 없으면 10초
$ docker build -t dangtong/fortune:args .
$ docker push dangtong/fortune:args
테스트를 위해 다음과 같이 수행 가능
$ docker run -it dangtong/fortune:args # 기본 10초 수행
$ docker run -it dangtong/fortune:args 15 # 15초로 매개변수 전달
8.1.3 Pod생성
파일명 : config-fortune-pod.yaml
cd ../../kubetmp
vi config-fortune-indocker-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: fortune5s
spec:
containers:
- image: dangtong/fortune:args
args: ["5"]
name: html-generator
volumeMounts:
- name: html
mountPath: /var/htdocs
- image: nginx:alpine
name: web-server
volumeMounts:
- name: html
mountPath: /usr/share/nginx/html
readOnly: true
ports:
- containerPort: 80
protocol: TCP
volumes:
- name: html
emptyDir: {}
kubectl apply -f ./config-fortune-indockeer-pod.yaml
8.2 Yaml 파일을 통한 매개변수 전달
8.2.1 fortuneloop.sh 작성
cd ../
mkdir -p ./docimg/inyaml
cd ./docimg/inyaml
vi fortuneloop.sh
#!/bin/bash
trap "exit" SIGINT
echo "Configured to generate neew fortune every " $INTERVAL " seconds"
mkdir /var/htdocs
while :
do
echo $(date) Writing fortune to /var/htdocs/index.html
/usr/games/fortune > /var/htdocs/index.html
sleep $INTERVAL
done
8.2.2 Dockerfile 작성 및 build
$ vi dockerfile
FROM ubuntu:latest
RUN apt-get update; apt-get -y install fortune
ADD fortuneloop.sh /bin/fortuneloop.sh
ENTRYPOINT ["/bin/fortuneloop.sh"]
CMD ["10"] # args가 없으면 10초
$ docker build -t dangtong/fortune:env .
$ docker push dangtong/fortune:env
8.2.2 Pod 생성및 매개변수 전달을 위한 yaml 파일 작성
cd ../../kubetmp
vi config-fortune-inyaml-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: fortune30s
spec:
containers:
- image: dangtong/fortune:env
env:
- name: INTERVAL
value: "30"
name: html-generator
volumeMounts:
- name: html
mountPath: /var/htdocs
- image: nginx:alpine
name: web-server
volumeMounts:
- name: html
mountPath: /usr/share/nginx/html
readOnly: true
ports:
- containerPort: 80
protocol: TCP
volumes:
- name: html
emptyDir: {}
8.3 ConfigMap 을 통한 설정
8.3.1 ConfigMap 생성 및 확인
- configMap 생성
$ kubectl create configmap fortune-config --from-literal=sleep-interval=7
ConfigMap 생성시 이름은 영문자,숫자, 대시, 밑줄, 점 만 포함 할 수 있습니다.
만약 여러개의 매개변수를 저장 할려면 –from-literal=sleep-interval=5 –from-literal=sleep-count=10 와 같이 from-literal 부분을 여러번 반복해서 입력 하면 됩니다.
- configMap 확인
$ kubectl get cm fortune-config
NAME DATA AGE
fortune-config 1 15s
$ kubectl get configmap fortune-config. -o yaml
apiVersion: v1
data:
sleep-interval: "7"
kind: ConfigMap
metadata:
creationTimestamp: "2020-04-16T09:09:33Z"
name: fortune-config
namespace: default
resourceVersion: "1044269"
selfLink: /api/v1/namespaces/default/configmaps/fortune-config
uid: 85723e0a-1959-4ace-9365-47c101ebef82
8.3.2 ConfigMap을 환경변수로 전달한는 yaml 파일 작성
- Yaml 파일 생성
vi config-fortune-mapenv-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: fortune7s
spec:
containers:
- image: dangtong/fortune:env
env:
- name: INTERVAL
valueFrom:
configMapKeyRef:
name: fortune-config
key: sleep-interval
name: html-generator
volumeMounts:
- name: html
mountPath: /var/htdocs
- image: nginx:alpine
name: web-server
volumeMounts:
- name: html
mountPath: /usr/share/nginx/html
readOnly: true
ports:
- containerPort: 80
protocol: TCP
volumes:
- name: html
emptyDir: {}
8.3.3 Pod 생성 및 확인
- Pod 생성
$ kubectl create -f ./config-fortune-mapenv-pod.yaml
- Pod 생성 확인
$ kubectl get po, cm
$ kubectl describe cm
Name: fortune-config
Namespace: default
Labels: <none>
Annotations: <none>
Data
====
sleep-interval:
----
7
Events: <none>
- configMap 삭제
$ kubectl delete configmap fortune-config
8.4 ConfigMap Volume 사용 (파일숨김-vm에서 수행)
8.4.1 ConfigMap 생성
mkdir config-dir
cd config-dir
vi custom-nginx-config.conf
파일명 : custom-nginx-config.conf
server {
listen 8080;
server_name www.acron.com;
gzip on;
gzip_types text/plain application/xml;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
}
$ kubectl create configmap fortune-config --from-file=config-dir
8.4.2 configMap volume 이용 Pod 생성
- Yaml 파일 작성 : config-fortune-mapvol-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx-configvol
spec:
containers:
- image: nginx:1.7.9
name: web-server
volumeMounts:
- name: ls
mountPath: /etc/nginx/conf.d
readOnly: true
ports:
- containerPort: 8080
protocol: TCP
volumes:
- name: config
configMap:
name: fortune-config
서버에 접속해서 디렉토리 구조를 한번 보는것이 좋습니다.
kubectl exec -it nginx-pod bash
$ kubectl apply -f ./config-fortune-mapvol-pod.yaml
8.4.3 ConfigMap Volume 참조 확인
$ kubectl get pod -o wide
AME READY STATUS RESTARTS AGE IP NODE
nginx-configvol 1/1 Running 0 9m25s 10.32.0.2 worker01.acorn.com
- Response 에 압축(gzip)을 사용 하는지 확인
$ curl -H "Accept-Encoding: gzip" -I 10.32.0.2:8080
- 마운트된 configMap 볼륨 내용확인
$ kubectl exec nginx-configvol -c web-server ls /etc/nginx/conf.d
nginx-config.conf
sleep-interval
$ kubectl exec -it nginx-configvol sh
8.4.4 ConfigMap 동적 변경
- 사전 테스트
$ curl -H "Accept-Encoding: gzip" -I 10.32.0.2:8080
HTTP/1.1 200 OK
Server: nginx/1.17.9
Date: Fri, 17 Apr 2020 06:10:32 GMT
Content-Type: text/html
Last-Modified: Tue, 03 Mar 2020 14:32:47 GMT
Connection: keep-alive
ETag: W/"5e5e6a8f-264"
Content-Encoding: gzip
- configMap 변경
$ kubectl edit cm fortune-config
gzip on 부분을 **gzip off ** 로 변경 합니다.
apiVersion: v1
data:
nginx-config.conf: "server {\n listen\t80;\n server_name\tnginx.acorn.com;\n\n
\ gzip off;\n gzip_types text/plain application/xml;\n location / {\n root\t/usr/share/nginx/html;\n
\ index\tindex.html index.htm;\n } \n}\n\n\n"
nginx-ssl-config.conf: '##Nginx SSL Config'
sleep-interval: |
25
kind: ConfigMap
metadata:
creationTimestamp: "2020-04-16T15:58:42Z"
name: fortune-config
namespace: default
resourceVersion: "1115758"
selfLink: /api/v1/namespaces/default/configmaps/fortune-config
uid: 182302d8-f30f-4045-9615-36e24b185ecb
- 변경후 테스트
$ curl -H "Accept-Encoding: gzip" -I 10.32.0.2:8080
HTTP/1.1 200 OK
Server: nginx/1.17.9
Date: Fri, 17 Apr 2020 06:10:32 GMT
Content-Type: text/html
Last-Modified: Tue, 03 Mar 2020 14:32:47 GMT
Connection: keep-alive
ETag: W/"5e5e6a8f-264"
Content-Encoding: gzip
- reload 로 변경 사항 컨테이너에 알리기
$ kubectl exec nginx-configvol -c web-server -- nginx -s reload
- 최종 테스트
$ curl -H "Accept-Encoding: gzip" -I 10.32.0.2:8080
HTTP/1.1 200 OK
Server: nginx/1.17.9
Date: Fri, 17 Apr 2020 06:10:32 GMT
Content-Type: text/html
Last-Modified: Tue, 03 Mar 2020 14:32:47 GMT
Connection: keep-alive
ETag: W/"5e5e6a8f-264"
8.5 ConfigMap Volume(파일 추가)
8.5.1 configMap volume 이용 Pod 생성
- Yaml 파일 작성 : config-fortune-mapvol-pod2.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx-configvol
spec:
containers:
- image: nginx:1.7.9
name: web-server
volumeMounts:
- name: config
mountPath: /etc/nginx/conf.d/default.conf
subPath: nginx-config.conf # 주의 : configmap 의 key 와 파일명이 일치 해야합니다.
readOnly: true
ports:
- containerPort: 8080
protocol: TCP
volumes:
- name: config
configMap:
name: fortune-config
defaultMode: 0660
nginx 1.7.9 이상 버전, 예를 들면 nginx:latest 로 하면 /etc/nginx/conf.d 폴더내에 default.conf 파일만 존재 합니다. Example_cat tssl.conf 파일은 없습니다. 테스트를 위해서 nginx:1.7.9 버전으로 설정 한것입니다.
$ kubectl apply -f ./config-fortune-mapvol-pod.yaml
8.5.2 서비스 및 ConfiMap 확인
- 서비스 확인
$ curl -H "Accept-Encoding: gzip" -I 10.32.0.2:8080
- configMap 확인
$ kubectl exec nginx-configvol -c web-server ls /etc/nginx/conf.d
8.5.3 ConfigMap 추가
- configMap 추가
$ kubectl edit cm fortune-config
아래와 같이 nginx-ssl-config.conf 키값을 추가합니다.
apiVersion: v1
data:
nginx-config.conf: "server {\n listen\t80;\n server_name\tnginx.acorn.com;\n\n
\ gzip on;\n gzip_types text/plain application/xml;\n location / {\n root\t/usr/share/nginx/html;\n
\ index\tindex.html index.htm;\n } \n}\n\n\n"
nginx-ssl-config.conf: ""##Nginx SSL Config" # 이부분이 추가됨
sleep-interval: |
25
kind: ConfigMap
metadata:
creationTimestamp: "2020-04-16T15:58:42Z"
name: fortune-config
namespace: default
resourceVersion: "1098337"
selfLink: /api/v1/namespaces/default/configmaps/fortune-config
uid: 182302d8-f30f-4045-9615-36e24b185ecb
8.5.4 ConfigMap 추가된 Pod 생성
- 설정 파일 추가 하기위해 yaml 파일 수정
파일명 : config-fortune-mapvol-pod3.yaml
kind: Pod
metadata:
name: nginx-configvol
spec:
containers:
- image: nginx:1.7.9
name: web-server
volumeMounts:
- name: config #default.conf 파일 교체
mountPath: /etc/nginx/conf.d/default.conf
subPath: nginx-config.conf
readOnly: true
- name: config #example_ssl.conf 파일 교체
mountPath: /etc/nginx/conf.d/example_ssl.conf
subPath: nginx-ssl-config.conf
readOnly: true
ports:
- containerPort: 8080
protocol: TCP
volumes:
- name: config
configMap:
name: fortune-config
defaultMode: 0660
$ kubectl apply -f ./ config-fortune-mapvol-pod3.yaml
8.5.6 추가된 ConfigMap 확인
- 서비스 확인
$ curl http://10.32.0.4
- configMap 확인
$ kubectl exec -it nginx-configvol bash
$ cd /etc/nginx/conf.d
$ ls -al
9. Secret
mkdir -p ./secret/cert
mkdir -p ./secret/config
mkdir -p ./secret/kubetmp
9.1 Secret 생성 (fortune-https)
cd ./secret/cert
openssl genrsa -out https.key 2048
openssl req -new -x509 -key https.key -out https.cert -days 360 -subj /CN=*.acron.com
kubectl create secret generic fortune-https --from-file=https.key --from-file=https.cert
9.2 SSL 용 niginx 설정 생성(fortune-config)
cd ./secret/config
vi custom-nginx-config.conf
server {
listen 8080;
listen 443 ssl;
server_name www.acron.com;
ssl_certificate certs/https.cert;
ssl_certificate_key certs/https.key;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers HIGH:!aNULL:!MD5;
gzip on;
gzip_types text/plain application/xml;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
}
vi sleep-interval
7
kubectl create cm fortune-config --from-file=./config
9.3 POD 생성
- Pod 생성 : 8.3.2 의 yaml 파일 참조
- 파일명 : secret-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: fortune-https
spec:
containers:
- image: dangtong/fortune:env
env:
- name: INTERVAL
valueFrom:
configMapKeyRef:
name: fortune-config
key: sleep-interval
name: html-generator
volumeMounts:
- name: html
mountPath: /var/htdocs
- image: nginx:alpine
name: web-server
volumeMounts:
- name: html
mountPath: /usr/share/nginx/html
readOnly: true
- name: config # 추가
mountPath: /etc/nginx/conf.d
readOnly: true
- name: certs # 추가
mountPath: /etc/nginx/certs/
readOnly: true
ports:
- containerPort: 80
- containerPort: 443 # 추가
volumes:
- name: html
emptyDir: {}
- name: config # 추가
configMap:
name: fortune-config
items:
- key: custom-nginx-config.conf
path: https.conf
- name: certs #추가
secret:
secretName: fortune-https
kubectl apply -f ./secret-pod.yaml
9.4 서비스 확인
kubectl port-forward fortune-https 8443:443 &
curl https://localhsot:8443 -k
curl https://localhost:8443 -k -v
[[Exercise #7]]
1. Mysql 구성하기
1.1 서비스 구성
파일명 : mysql-svc.yaml
apiVersion: v1
kind: Service
metadata:
name: wordpress-mysql
labels:
app: wordpress
spec:
ports:
- port: 3306
selector:
app: wordpress
tier: mysql
clusterIP: None
1.2 볼륨 구성
파일명 : mysql-pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mysql-pv-claim
labels:
app: wordpress
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 20Gi
1.3 Pod 구성
파일명 : mysql-deploy.yaml
apiVersion: apps/v1 # for versions before 1.9.0 use apps/v1beta2
kind: Deployment
metadata:
name: wordpress-mysql
labels:
app: wordpress
spec:
selector:
matchLabels:
app: wordpress
tier: mysql
strategy:
type: Recreate
template:
metadata:
labels:
app: wordpress
tier: mysql
spec:
containers:
- image: mysql:5.6
name: mysql
env:
- name: MYSQL_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: mysql-pass
key: password
ports:
- containerPort: 3306
name: mysql
volumeMounts:
- name: mysql-persistent-storage
mountPath: /var/lib/mysql
volumes:
- name: mysql-persistent-storage
persistentVolumeClaim:
claimName: mysql-pv-claim
kubectl apply -f
2. WordPress 서비스 구성
2.1 LoadBalancer 구성
apiVersion: v1
kind: Service
metadata:
name: wordpress
labels:
app: wordpress
spec:
ports:
- port: 80
selector:
app: wordpress
tier: frontend
type: LoadBalancer
2.2 PVC 구성
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: wp-pv-claim
labels:
app: wordpress
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 20Gi
2.3 WordPress 구성
apiVersion: apps/v1
kind: Deployment
metadata:
name: wordpress
labels:
app: wordpress
spec:
selector:
matchLabels:
app: wordpress
tier: frontend
strategy:
type: Recreate
template:
metadata:
labels:
app: wordpress
tier: frontend
spec:
containers:
- image: wordpress:4.8-apache
name: wordpress
env:
- name: WORDPRESS_DB_HOST
value: wordpress-mysql
- name: WORDPRESS_DB_PASSWORD
valueFrom:
secretKeyRef:
name: mysql-pass
key: password
ports:
- containerPort: 80
name: wordpress
volumeMounts:
- name: wordpress-persistent-storage
mountPath: /var/www/html
volumes:
- name: wordpress-persistent-storage
persistentVolumeClaim:
claimName: wp-pv-claim
10. StatefullSet (GCP 수행)
10.1 애플리케이션 이미지 작성
10.1.1 app.js 작성
const http = require('http');
const os = require('os');
const fs = require('fs');
const dataFile = "/var/data/kubia.txt";
const port = 8080;
// 파일 존재 유/무 검사
function fileExists(file) {
try {
fs.statSync(file);
return true;
} catch (e) {
return false;
}
}
var handler = function(request, response) {
// POST 요청일 경우 BODY에 있는 내용을 파일에 기록 함
if (request.method == 'POST') {
var file = fs.createWriteStream(dataFile);
file.on('open', function (fd) {
request.pipe(file);
console.log("New data has been received and stored.");
response.writeHead(200);
response.end("Data stored on pod " + os.hostname() + "\n");
});
// GET 요청일 경우 호스트명과 파일에 기록된 내용을 반환 함
} else {
var data = fileExists(dataFile) ? fs.readFileSync(dataFile, 'utf8') : "No data posted yet";
response.writeHead(200);
response.write("You've hit " + os.hostname() + "\n");
response.end("Data stored on this pod: " + data + "\n");
}
};
var www = http.createServer(handler);
www.listen(port);
10.1.2 Docker 이미지 만들기
- Dockerfile 작성
FROM node:7
ADD app.js /app.js
ENTRYPOINT ["node", "app.js"]
- Docker 이미지 build 및 push
$ docker build dangtong/nodejs:sfs .
$ docker login
$ docker push dangtong/nodejs:sfs
10.2 PVC 생성
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: sc-standard-retain
provisioner: kubernetes.io/gce-pd
reclaimPolicy: Retain
parameters:
type: pd-ssd
zone: asia-northeast1-c
10.3 서비스 및 Pod 생성
10.3.1 로드밸런서 서비스 생성
apiVersion: v1
kind: Service
metadata:
name: nodesjs-sfs-lb
spec:
type: LoadBalancer
ports:
- port: 80
targetPort: 8080
selector:
app: nodejs-sfs
10.3.2 Pod 생성
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: nodejs-sfs
spec:
selector:
matchLabels:
app: nodejs-sfs
serviceName: nodejs-sfs
replicas: 2
template:
metadata:
labels:
app: nodejs-sfs
spec:
containers:
- name: nodejs-sfs
image: dangtong/nodejs:sfs
ports:
- name: http
containerPort: 8080
volumeMounts:
- name: data
mountPath: /var/data
volumeClaimTemplates:
- metadata:
name: data
spec:
resources:
requests:
storage: 1Mi
accessModes:
- ReadWriteOnce
storageClassName: sc-standard-retain
kubectl apply -f nodejs-sfs.yaml
kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.65.0.1 <none> 443/TCP 7h43m
service/nodesjs-sfs-lb LoadBalancer 10.65.12.243 34.85.38.158 80:32280/TCP 120m
10.4 서비스 테스트
- 데이터 조회
curl http://34.85.38.158
- 데이터 입력
curl -X POST -d "hi, my name is dangtong-1" 34.85.38.158
curl -X POST -d "hi, my name is dangtong-2" 34.85.38.158
curl -X POST -d "hi, my name is dangtong-3" 34.85.38.158
curl -X POST -d "hi, my name is dangtong-4" 34.85.38.158
데이터 입력을 반복하에 두개 노드 모드에 데이터를 모두 저장 합니다. 양쪽 노드에 어떤 데이터가 입력 되었는지 기억 하고 다음 단계로 넘어 갑니다.
10.5 노드 삭제 및 데이터 보존 확인
- 노드 삭제 및 자동 재생성
kubectl delete pod nodejs-sfs-0
노드를 삭제 한뒤 노드가 재생성 될때 까지 기다립니다.
- 데이터 보존 확인
curl http://34.85.38.158
노드가 삭제 되었다 재생성 되도 기존 디스크를 그대로 유지하는 것을 볼 수 있습니다. ReclaimPolicy 를 Retain 으로 했기 때문 입니다.
11. 리소스 제어
11.1 부하 발생용 애플리 케이션 작성
11.1.1 PHP 애플리 케이션 작성
파일명 : index.php
<?php
$x = 0.0001;
for ($i = 0; $i <= 1000000; $i++) {
$x += sqrt($x);
}
echo "OK!";
?>
11.1.2 도커 이미지 빌드
FROM php:5-apache
ADD index.php /var/www/html/index.php
RUN chmod a+rx index.php
docker build -t dangtong/php-apache .
docker login
docker push dangtong/php-apache
11.2 포드 및 서비스 만들기
12.2.1 Deployment 로 Pod 새성
파일명 : php-apache-deploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: php-apache-dp
spec:
selector:
matchLabels:
app: php-apache
replicas: 1
template:
metadata:
labels:
app: php-apache
spec:
containers:
- name: php-apache
image: dangtong/php-apache
ports:
- containerPort: 80
resources:
limits:
cpu: 500m
requests:
cpu: 200m
12.2.2 로드밸런서 서비스 작성
파일명 : php-apache-svc.yaml
apiVersion: v1
kind: Service
metadata:
name: php-apache-lb
spec:
type: LoadBalancer
ports:
- port: 80
targetPort: 80
selector:
app: php-apache
kubectl apply -f ./php-apache-deploy.yaml
kubectl apply -f ./php-apache-svc.yaml
[[연습 문제]]
아래 요구 사항에 맞는 deploy 를 구현 하세요
- Deploy name : nginx
- image : nginx
- cpu 200m
- 메모리 : 300Mi
- Port : 80
12.3 HPA 리소스 생성
12.3.1 HPA 리소스 생성
kubectl autoscale deployment php-apache --cpu-percent=50 --min=1 --max=5
12.3.2 HPA 리소스 생성 확인
kubectl get hpa
12.4 Jmeter 설치 및 구성
12.4.1 Jmeter 설치를 위00000해 필요한 것들
- JDK 1.8 이상 설치 오라클 java SE jdk 다운로드
- Jmeter 다운로드 Jmeter 다운로드
- Jmeter 플러그인 다운로드 Jmeter-plugin 다운로드
- Plugins-manager.jar 다운로드 하여 jmeter 내에 lib/ext 밑에 복사 합니다.
12.4.2 Jmeter 를 통한 부하 발생
12.4.3 부하 발생후 Pod 모니터링
$ kubectl get hpa
$ kubectl top pods
NAME CPU(cores) MEMORY(bytes)
nodejs-sfs-0 0m 7Mi
nodejs-sfs-1 0m 7Mi
php-apache-6997577bfc-27r95 1m 9Mi
$ kubectl exec -it nodejs-sfs-0 top
Tasks: 2 total, 1 running, 1 sleeping, 0 stopped, 0 zombie
%Cpu(s): 4.0 us, 1.0 sy, 0.0 ni, 95.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
KiB Mem: 3786676 total, 3217936 used, 568740 free, 109732 buffers
KiB Swap: 0 total, 0 used, 0 free. 2264392 cached Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
1 root 20 0 813604 25872 19256 S 0.0 0.7 0:00.17 node
11 root 20 0 21924 2408 2084 R 0.0 0.1 0:00.00 top
[[Exercise]]
이미지를 nginx 를 생성하고 HPA 를 적용하세요
- Max : 8
- Min : 2
- CPU 사용량이 40% 가 되면 스케일링 되게 하세요
13. Kubernetes DashBoard 설치
13.1 Dashboard 설치
참조 URL : https://kubernetes.io/ko/docs/tasks/access-application-cluster/web-ui-dashboard/
kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.0.0/aio/deploy/recommended.yaml
13.2 DashBoard 인증서 생성
mkdir -p ./kubeSrc/dashboard/certs
mkdir -p ./kubeSrc/dashboard/yaml
cd ./kubeSrc/dashboard/certs
13.2.1 개인키 생성
openssl genrsa -des3 -out dashboard-private.key 2048
Generating RSA private key, 2048 bit long modulus (2 primes)
.....................................................................................+++++
...........................................+++++
e is 65537 (0x010001)
Enter pass phrase for dashboard-private.key:
Verifying - Enter pass phrase for dashboard-private.key:
# openssl rsa --noout -text -in dashboard-private.key
13.2.1 공개키 생성
openssl rsa -in dashboard-private.key -out dashboard-public.key
13.2.2 CSR 생성
openssl req -new -key dashboard-public.key -out dashboard.csr
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:KR
State or Province Name (full name) [Some-State]:Seoul
Locality Name (eg, city) []:Guro-Gu
Organization Name (eg, company) [Internet Widgits Pty Ltd]:acorn
Organizational Unit Name (eg, section) []:edu
Common Name (e.g. server FQDN or YOUR name) []:*.acorn.com
Email Address []:dangtong@gmail.com
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:admin123
An optional company name []:acorn
13.2.3 인증서 생성
openssl x509 -req -sha256 -days 3650 -in dashboard.csr -signkey dashboard-public.key -out kubernetes-dashboard.crt
13.3 DashBoard 생성
13.3.1 네임스페이스 및 Secret 생성
- 네임스페이스 생성
kubectl create namespace kubernetes-dashboard
- Secret 생성
kubectl create secret generic kubernetes-dashboard-certs --from-file=$HOME/kubeSrc/dashboard/certs -n kubernetes-dashboard
- Secret 확인
kubectl get secret -n kubernetes-dashboard-certs -n kubernetes-dashboard
13.3.2 DashBoard Deployment
kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.0.0/aio/deploy/recommended.yaml
13.3.3 ClusterIP 를 NodePort 방식으로 변경
kubectl edit service kubernetes-dashboard -n kubernetes-dashboard
...
ports:
- nodePort: 30812 # 이부분 추가
port: 443
protocol: TCP
targetPort: 8443
selector:
k8s-app: kubernetes-dashboard
sessionAffinity: None
type: NodePort # 이부분 변경
13.3.4 서비스 확인
kubectl get service -n kubernetes-dashboard
13.2.
13.2 NodePort 서비스
spec:
clusterIP: 10.103.46.146
ports:
- port: 443
protocol: TCP
targetPort: 8443
nodePort: 30124
selector:
k8s-app: kubernetes-dashboard
sessionAffinity: None
type: NodePort
status:
loadBalancer: {}
13.2 Client 인증서 만들기
- kubectl 의 key 복사
grep 'client-key-data' ~/.kube/config | head -n 1 | awk '{print $2}' | base64 -d >> kubecfg.key
- 인증서 생성
# CSR 생성
openssl req -new -key kubecfg.key -out kubecfg.csr -subj "/CN=admin-user"
# 인증서 생성
sudo openssl x509 -req -in kubecfg.csr -CA /etc/kubernetes/pki/ca.crt -CAkey /etc/kubernetes/pki/ca.key -CAcreateserial -out kubecfg.crt -days 500
- 브라우저에서 사용 가능한 PKCS#12 양식으로 변환 합니다
openssl pkcs12 -export -clcerts -inkey kubecfg.key -in kubecfg.crt -out kubecfg.p12 -name "admin-user"
- CA 인증서를 복사합니다.
cp /etc/kubernetes/pki/ca.crt .
kubeadmin@kmaster:~/kubeSrc/dashboard$ ls
ca.crt kubecfg.crt kubecfg.csr kubecfg.key kubecfg.p12
- Sftp 로 서버에 접속해서 kubecfg.crt / kubecfg.p12 / ca.crt 파일을 다운로드 받습니다.
13.3 인증서
13.3.1 윈도우 인증서 Import
- 윈도우 Root CA 인증서 Import
C:\Windows\system32>certutil.exe -addstore "Root" C:\Users\dangtong\Documents\ca.crt
Root "신뢰할 수 있는 루트 인증 기관"
서명이 공개 키와 일치합니다.
"kubernetes" 인증서가 저장소에 추가되었습니다.
CertUtil: -addstore 명령이 성공적으로 완료되었습니다.
- PKCS#12 인증서 Imort
C:\Windows\system32>certutil.exe -p admin123 -user -importPFX
C:\Users\dangtong\Documents\kubecfg.p12
"kubernetes-admin" 인증서가 저장소에 추가되었습니다.
CertUtil: -importPFX 명령이 성공적으로 완료되었습니다.
13.3.2 OSX 인증서 Import
- Root CA 인증서 Import
security add-trusted-cert -r trustRoot -k "$HOME/Library/Keychains/login.keychain" /Users/dangtong/kube-dashboard/ca.crt
- PKCS#12 인증서 Import
security import /Users/dangtong/kube-dashboard/kubecfg.p12 -k "$HOME/Library/Keychains/login.keychain" -P admin123
13.4 서비스 어카운트 및 롤생성
13.4.1 서비스 어카운트 생성
파일명 : admin-user.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: admin-user
namespace: kubernetes-dashboard
13.4.2 롤생성
파일명 : admin-user-role.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: admin-user-role-binding
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- kind: ServiceAccount
name: admin-user
namespace: kubernetes-dashboard
kubectl apply -f ./admin-user.yaml
kubectl apply -f ./admin-user-role.yaml
13.4.3 인증 토큰 조회
아래 명령을 수행해서 인증 토큰을 복사 합니다.
kubectl -n kubernetes-dashboard describe secret $(kubectl -n kubernetes-dashboard get secret | grep admin-user | awk '{print $1}')
Name: admin-user-token-28l6n
Namespace: kubernetes-dashboard
Labels: <none>
Annotations: kubernetes.io/service-account.name: admin-user
kubernetes.io/service-account.uid: d3f6b3d6-63f3-4483-88f0-dc8e6f37ffd8
Type: kubernetes.io/service-account-token
Data
====
ca.crt: 1025 bytes
namespace: 20 bytes
token: eyJhbGciOiJSUzI1NiIsImtpZCI6InEwaS1COEtFcjNwd0RBbE1KUHpaNTZuZlBlSmY4a1Nld1FZYjhIam5ZV2cifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlcm5ldGVzLWRhc2hib2FyZCIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJhZG1pbi11c2VyLXRva2VuLTI4bDZuIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQubmFtZSI6ImFkbWluLXVzZXIiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC51aWQiOiJkM2Y2YjNkNi02M2YzLTQ0ODMtODhmMC1kYzhlNmYzN2ZmZDgiLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6a3ViZXJuZXRlcy1kYXNoYm9hcmQ6YWRtaW4tdXNlciJ9.JB1hGeIxJyU-0VbOmMGcp0b6B758nqGAXhgBFOj9eZMj73h7BNizO4aEiDMsJgH3tvtXRxChUHIMFT0kBeX6i7U-3GYvS_Uw7XNREYdhrYl8PVoPcqcXi7tL1tTrCEj-Rxy7HxyHXGGwb6wJYO11BgzuwCLJWjm-i-G3N3yrzi8KQ7MjWKVPisrxgPna_dKO6LgrCiq6oVO14FFVbwB6IqdiH8jpHrH2GSIKjFCAAziHSoHBLbc6qv5_9hle5CaO6LZxTlZCt4H7drWnUUyVmjz1sqkUZg08EVfewVzZCQXPig6Rj3DTGbFrzg1Zk3h3EBJq4VhjnCYj1ePNDw_-eg
13.5 DashBoard 접속
- 접속 URL
https://192.168.56.111:6443/api/v1/namespaces/kubernetes-dashboard/services/https:kubernetes-dashboard:/proxy/
토큰 을 선택하고 복사한 토큰을 토큰입력 란에 붙여넣고 로그인 합니다.
13.6 삭제
kubectl --namespace kube-system delete deployment,service kubernetes-dashboard
14. 계정 및 인증
14.1 User Account 및 RBAC 사용
14.1.1 유저 생성
# root 로 수행
adduser devuser
su - devuser
# devuser 로 수행
mkdir .cert
mkdir .kube
14.1.2 유저 인증서 생성(root 로 수행)
- 인증서 생성
cd ~
mkdir devuser-cert
cd devuser-cert
# 키생성
openssl genrsa -out devuser.key 2048
# CSR 생성
openssl req -new -key devuser.key -out devuser.csr -subj "/CN=devuser/O=devuser"
# 인증서 생성
openssl x509 -req -in devuser.csr -CA /etc/kubernetes/pki/ca.crt -CAkey /etc/kubernetes/pki/ca.key -CAcreateserial -out devuser.crt -days 500
- 인증서 복사
cp devuser.crt /home/devuser/.cert/
cp devuser.key /home/devuser/.cert/
chown -R devuser:devuser /home/devuser/.cert
14.1.3 kubectl 로 config 파일 만들기(devuser 로 수행)
- API 서버 접속 및 CA 인증서 설정
cd ~/.kube
kubectl config --kubeconfig=config set-cluster devuser-cluster --server=https://192.168.56.111:6443 --certificate-authority=/etc/kubernetes/pki/ca.crt
cat ~/.kube/config
- 사용자 접속 정보 (인증서 정보 설정)
kubectl config --kubeconfig=config set-credentials devuser --client-certificate=/home/devuser/.cert/devuser.crt --client-key=/home/devuser/.cert/devuser.key
- 컨텍스트 설정
kubectl config --kubeconfig=config set-context devuser-context --cluster=devuser-cluster --namespace=dev --user=devuser
cat ~/.kube/config
- 테스트
kubectl get pod
The connection to the server localhost:8080 was refused - did you specify the right host or port?
kubectl --context=devuser-context get po
Error from server (Forbidden): pods is forbidden: User "devuser" cannot list resource "pods" in API group "" in the namespace "dev"
메시지가 왜 다른지 생각 해봅시다. config 를 열어서 current-context: "devuser-context" 로 수정한 후 다시 수행 합니다.
14.1.4 네임스페이스 생성 (root 로 수행)
kubectl create namespace dev
14.1.5 롤생성 (root 로 수행)
파일명 : dev-role.yaml
kind: Role
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
namespace: dev
name: dev-role
rules:
- apiGroups: ["", "extensions", "apps"]
resources: ["deployments", "replicasets", "pods"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
kubectl apply -f ./dev-role.yaml
Verb | 설명 |
---|---|
create | 리소스 생성 |
get | 리소스 조회 |
list | 여러건 리소스 동시 조회 |
update | 리소스 전체 내용 업데이트 |
patch | 리소스 일부 내용 변경 |
delete | 단일 리소스 삭제 |
Delete collection | 여러 리소스 삭제 |
resource 뿐만 아니라 resourceNames 를 지정해서 특정 Pod 나 리소스에 대한 권한 으로 제한 할 수도 있음
14.1.6 롤바인딩 생성 (root 로 수행)
파일명 : dev-role-bind.yaml
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
name: dev-role-binding
namespace: dev
subjects:
- kind: User
name: devuser
apiGroup: ""
roleRef:
kind: Role
name: dev-role
apiGroup: ""
kubectl apply -f ./dev-role-bind.yaml
14.1.7 테스트 Pod 생성 및 테스트 (devuser 로 수행)
# 사용 가능한 context 확인
kubectl config get-contexts
# context로 전환
kubectl config use-context devuser-context
# 현재 사용중인 context 확인
kubectl config current-context
kubectl --context=devuser-context run --generator=run-pod/v1 nginx --image=nginx --port=80 --dry-run -o yaml > nginx-pod.yaml
kubectl apply -f ./nginx-pod.yaml
kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx 1/1 Running 0 2m39s 10.40.0.8 worker01.acorn.com <none> <none>
curl http://10.40.0.8
14.2 Service Account 및 RBAC
14.2.1 Service Account 생성
- Service Account 생성
kubectl create sa apiuser
# kubectl create sa apiuser --dry-run -o yaml
kubectl get sa
kubectl get sa --all-namespaces
- 토큰 Secret 생성
apiVersion: v1
kind: Secret
metadata:
name: apiuser-secret
annotations:
kubernetes.io/service-account.name: apiuser
type: kubernetes.io/service-account-token
kubectl describe secrets/apiuser-secret
14.2.2 롤 생성
- 롤 생성
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: read-role
namespace: default
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list"]
14.2.3 롤 바인딩
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: read-role-binding
namespace: default
subjects:
- kind: ServiceAccount
name: apiuser
apiGroup: ""
roleRef:
kind: Role
name: read-role
apiGroup: kube
14.2.4 토큰 인코딩 및 서비스 테스트
- 토큰 인코딩
kubectl get secret apiuser-secret -o yaml
apiVersion: v1
kind: ServiceAccount
metadata:
creationTimestamp: "2020-04-30T19:48:15Z"
name: apiuser
namespace: default
resourceVersion: "1715742"
selfLink: /api/v1/namespaces/default/serviceaccounts/apiuser
uid: 3b658e4a-ec4f-4eda-b790-ba74d0607973
secrets:
- name: apiuser-token-llvcb # 토큰
kubectl get secrets apiuser-token-llvcb -o json | jq -Mr '.data.token' | base64 -d
- Pod 리스트 조회
curl -k https://192.168.56.111:6443/api/v1/namespaces/default/pods/ -H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6InEwaS1COEtFcjNwd0RBbE1KUHpaNTZuZlBlSmY4a1Nld1FZYjhIam5ZV2cifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJkZWZhdWx0Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZWNyZXQubmFtZSI6ImFwaXVzZXItdG9rZW4tbGx2Y2IiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC5uYW1lIjoiYXBpdXNlciIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50LnVpZCI6IjNiNjU4ZTRhLWVjNGYtNGVkYS1iNzkwLWJhNzRkMDYwNzk3MyIsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDpkZWZhdWx0OmFwaXVzZXIifQ.qVfF3Tt9fAI6uC8CfyiuSBYnYU8z8sLQIRt3sH0B3zgpcToxPY9aAuoADmg-ULUQJBJjiBgbhWxy1ujpJwKy-jLb-0-MqIype2Z58dlNCOupaWnFDzYMJr9XLL33L6KD7SSVTp22CP89KGj_TxDdOrLj6jQi07WGBBqsliCPu5xy1p6SoiOdl-FxWpHqJxfhgtpVX1ntPA_DN6H_CiFPvvKoaWAy76HzH79aMbdmtR4NDpKYoCo1vbNmnWuQ2571lL4einBKkHj8bi0zeBa1cKvuqTUHftGV4KDYQ0nsX1R7Ispk3XNuMLgx7Lxl6idDUxfDkeRElZraMo3FgMYN0w"
- 특정 Pod 조회
curl -k https://192.168.56.111:6443/api/v1/namespaces/default/pods/goapp-deployment-5857594fbb-46ckf -H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6InEwaS1COEtFcjNwd0RBbE1KUHpaNTZuZlBlSmY4a1Nld1FZYjhIam5ZV2cifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJkZWZhdWx0Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZWNyZXQubmFtZSI6ImFwaXVzZXItdG9rZW4tbGx2Y2IiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC5uYW1lIjoiYXBpdXNlciIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50LnVpZCI6IjNiNjU4ZTRhLWVjNGYtNGVkYS1iNzkwLWJhNzRkMDYwNzk3MyIsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDpkZWZhdWx0OmFwaXVzZXIifQ.qVfF3Tt9fAI6uC8CfyiuSBYnYU8z8sLQIRt3sH0B3zgpcToxPY9aAuoADmg-ULUQJBJjiBgbhWxy1ujpJwKy-jLb-0-MqIype2Z58dlNCOupaWnFDzYMJr9XLL33L6KD7SSVTp22CP89KGj_TxDdOrLj6jQi07WGBBqsliCPu5xy1p6SoiOdl-FxWpHqJxfhgtpVX1ntPA_DN6H_CiFPvvKoaWAy76HzH79aMbdmtR4NDpKYoCo1vbNmnWuQ2571lL4einBKkHj8bi0zeBa1cKvuqTUHftGV4KDYQ0nsX1R7Ispk3XNuMLgx7Lxl6idDUxfDkeRElZraMo3FgMYN0w"
14.3 클러스터롤 과 집계 클러스터롤
14.3.1 클러스터롤 생성
vi read-clusterrole.yaml
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: read-cluster-role
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list"]
14.2.3 Aggregation 클러스터룰 생성
- 생성
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: agg-cluster-role
aggregationRule:
clusterRoleSelectors:
- matchLabels:
kubernetes.io/bootstrapping: rbac-defaults
rules: []
- 확인
kubectl get clusterrole cluster-admin -o yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
annotations:
rbac.authorization.kubernetes.io/autoupdate: "true"
creationTimestamp: "2020-04-30T06:02:28Z"
labels:
kubernetes.io/bootstrapping: rbac-defaults
name: cluster-admin
resourceVersion: "38"
selfLink: /apis/rbac.authorization.k8s.io/v1/clusterroles/cluster-admin
14.2.3 롤바인딩
- 테스트용 유저 생성
apiVersion: v1
kind: ServiceAccount
metadata:
name: myuser
namespace: default
- 클러스터롤 바인딩
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: read-cluster-role-binding
subjects:
- kind: ServiceAccount
name: myuser
namespace: default
apiGroup: ""
roleRef:
kind: ClusterRole
name: read-cluster-role # 미리 만든 클러스터롤을 유저에 바인딩 합니다
apiGroup: rbac.authorization.k8s.io
- Aggregation 클러스터 롤 바인딩
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: agg-cluster-role-binding
subjects:
- kind: ServiceAccount
name: myuser
namespace: default
apiGroup: ""
roleRef:
kind: ClusterRole
name: agg-cluster-role # 미리 만든 클러스터롤을 유저에 바인딩 합니다
apiGroup: rbac.authorization.k8s.io
15. 테인트(Taint) 와 톨러레이션(Tolerations)
- tain : 노드마다 설정 가능 하며, 설정한 노드에는 Pod 가 스케줄 되지 않음
- Toleration: taint를 무시 할 수 있음
- Taint 에는 3가지 종류가 있음
Taint | 설명 |
---|---|
NoSchedule | toleration이 없으면 pod이 스케쥴되지 않음, 기존 실행되던 pod에는 적용 안됨 |
PreferNoSchedule | toleration이 없으면 pod을 스케줄링안하려고 하지만 필수는 아님, 클러스터내에 자원이 부족하거나 하면 taint가 걸려있는 노드에서도 pod이 스케줄링될 수 있음 |
NoExecute | toleration이 없으면 pod이 스케줄되지 않으며 기존에 실행되던 pod도 toleration이 없으면 종료시킴. |
15.1 노드에 Taint 설정하기
15.1.1 Taint 설정
kubectl taint node worker01.acorn.com key=value1:NoSchedule
15.1.2 Taint 조회
kubectl describe node worker01.acorn.com
node/worker01.acorn.com tainted
root@master:~# kubectl describe node worker01.acorn.com
Name: worker01.acorn.com
Roles: <none>
Labels: beta.kubernetes.io/arch=amd64
beta.kubernetes.io/os=linux
disk=ssd
kubernetes.io/arch=amd64
kubernetes.io/hostname=worker01.acorn.com
kubernetes.io/os=linux
Annotations: kubeadm.alpha.kubernetes.io/cri-socket: /var/run/dockershim.sock
node.alpha.kubernetes.io/ttl: 0
volumes.kubernetes.io/controller-managed-attach-detach: true
CreationTimestamp: Wed, 18 Mar 2020 15:48:26 +0000
Taints: key=value1:NoSchedule
Unschedulable: false
Lease:
HolderIdentity: worker01.acorn.com
15.2 DaemonSet 생성
15.2.1 Yaml 파일 작성
파일명 : goapp-daemon.yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: goapp-damonset
spec:
selector:
matchLabels:
app: goapp-pod
template:
metadata:
labels:
app: goapp-pod
spec:
containers:
- name: goapp-container
image: dangtong/goapp
kubectl apply -f ./goapp-daemon.yaml
15.2.2 DaemonSet 생성 확인
kubectl get po -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
goapp-damonset-bmwfq 1/1 Running 0 18s 10.38.0.3 worker02.acorn.com <none> <none>
Master 노드와 worker01 에는 스케줄링 되지 않았습니다.
- master 노드의 taint 확인
kubectl describe node master.acorn.com | grep -i taint
Taints: node-role.kubernetes.io/master:NoSchedule
- worker01 노드의 Taint 확인
kubectl describe node worker01.acorn.com | grep -i taint
Taints: key=value1:NoSchedule
- DaemonSet 삭제
kubectl delete ds goapp-damonset
15.2.3 Toleration 을 적용한 DaemonSet 생성
- Yaml 파일 작성 : goal-daemon-toler.yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: goapp-damonset
spec:
selector:
matchLabels:
app: goapp-pod
template:
metadata:
labels:
app: goapp-pod
spec:
tolerations:
- key: key
operator: Equal
value: value1
effect: NoSchedule
containers:
- name: goapp-container
image: dangtong/goapp
kubectl apply -f ./goapp-daemon-toler.yaml
- DaemonSet 생성 확인
kubectl get po -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
goapp-damonset-74klq 1/1 Running 0 35s 10.38.0.3 worker02.acorn.com <none> <none>
goapp-damonset-dr4xz 1/1 Running 0 35s 10.40.0.2 worker01.acorn.com <none> <none>
Pod 가 Taint 를 무시하고 worker01 에도 생성 된것을 확인 할 수 있습니다.
- 다음 테스트를 위해 DaemonSet 삭제
kubectl delete ds goapp-damonset
- Mater 노드에도 DaemonSet 생성을 위해 Yaml 파일 수정
kubectl describe no master.acorn.com | grep -i taint
Taints: node-role.kubernetes.io/master:NoSchedule
master 노드의 Taint 에는 key 와 effect 만 존재함
- Master 노드에 스케줄링이 가능 하도록 Yaml 파일 작성 : goapp-damon-toler-all.yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: goapp-damonset
spec:
selector:
matchLabels:
app: goapp-pod
template:
metadata:
labels:
app: goapp-pod
spec:
tolerations:
- key: key
operator: Equal
value: value1
effect: NoSchedule
- key: node-role.kubernetes.io/master
operator: Exists
effect: NoSchedule
containers:
- name: goapp-container
image: dangtong/goapp
kubectl apply -f ./goapp-daemon-toler-all.yaml
- 다음 테스트를 위해 DaemonSet 삭제
kubectl delete ds goapp-daemonset
15.2.4 untaint 명령으로 노드의 Taint 해지하고 스케줄링 하기
- Untaint 설정 하기
kubectl describe no worker01.acorn.com | grep -i taint
Taints: key=value1:NoSchedule
kubectl taint nodes --all key-
키값 뒤에 "-" 를 붙여 taint 를 해지 합니다. (untaint)
- daemonSet yaml 파일 재수행
kubectl apply -f ./goapp-daemonset.yaml
- 확인
kubectl get po -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
goapp-damonset-lj2z7 1/1 Running 0 14s 10.40.0.2 worker01.acorn.com <none> <none>
goapp-damonset-vhlq2 1/1 Running 0 15s 10.38.0.3 worker02.acorn.com <none> <none>
16. 노드 패치및 업그레이드를 위한 Cordon 과 Drain 사용하기
16.1 Cordon 사용하기
kubectl get nodes
NAME STATUS ROLES AGE VERSION
gke-cluster-1-default-pool-20e07d73-4ksw Ready <none> 28h v1.14.10-gke.27
gke-cluster-1-default-pool-20e07d73-6mr8 Ready <none> 28h v1.14.10-gke.27
gke-cluster-1-default-pool-20e07d73-8q3g Ready <none> 28h v1.14.10-gke.27
- cordon 설정
kubectl cordon gke-cluster-1-default-pool-20e07d73-6mr8
kubectl get nodes
NAME STATUS ROLES AGE VERSION
gke-cluster-1-default-pool-20e07d73-4ksw Ready <none> 28h v1.14.10-gke.27
gke-cluster-1-default-pool-20e07d73-6mr8 Ready,SchedulingDisabled <none> 28h v1.14.10-gke.27
gke-cluster-1-default-pool-20e07d73-8q3g Ready <none> 28h v1.14.10-gke.27
- 실제로 스케줄링 되지 않는지 확인해보기
kubectl run nginx --image=nginx:1.7.8 --replicas=4 --port=80
- 스케줄링 확인
kubectl get po -o wide
NAME READY STATUS RESTARTS AGE IP NODE
NOMINATED NODE READINESS GATES
nginx-84569d7db5-cgf95 1/1 Running 0 9s 10.4.0.17 gke-cluster-1-default-pool-20e07d73-8q3g
<none> <none>
nginx-84569d7db5-d7cgg 1/1 Running 0 8s 10.4.1.8 gke-cluster-1-default-pool-20e07d73-4ksw
<none> <none>
nginx-84569d7db5-gnbnq 1/1 Running 0 9s 10.4.1.9 gke-cluster-1-default-pool-20e07d73-4ksw
<none> <none>
nginx-84569d7db5-xqn7b 1/1 Running 0 9s 10.4.0.16 gke-cluster-1-default-pool-20e07d73-8q3g
<none> <none>
- uncodon 설정
kubectl uncordon gke-cluster-1-default-pool-20e07d73-6mr8
kubectl get nodes
16.2 Drain 사용하기
- Drain 설정
kubeclt get po -o wide
NAME READY STATUS RESTARTS AGE IP NODE
NOMINATED NODE READINESS GATES
nginx-84569d7db5-cgf95 1/1 Running 0 3m44s 10.4.0.17 gke-cluster-1-default-pool-20e07d73-8q
3g <none> <none>
nginx-84569d7db5-d7cgg 1/1 Running 0 3m43s 10.4.1.8 gke-cluster-1-default-pool-20e07d73-4k
sw <none> <none>
nginx-84569d7db5-gnbnq 1/1 Running 0 3m44s 10.4.1.9 gke-cluster-1-default-pool-20e07d73-4k
sw <none> <none>
nginx-84569d7db5-xqn7b 1/1 Running 0 3m44s 10.4.0.16 gke-cluster-1-default-pool-20e07d73-8q
3g <none> <none>
- Pod 가 존재 하는 노드를 drain 모드로 설정하기
kubectl drain gke-cluster-1-default-pool-20e07d73-8q3g
error: unable to drain node "gke-cluster-1-default-pool-20e07d73-8q3g", aborting command...
There are pending nodes to be drained:
gke-cluster-1-default-pool-20e07d73-8q3g
error: cannot delete DaemonSet-managed Pods (use --ignore-daemonsets to ignore): kube-system/fluentd-gcp-v3.1.1-
t6mnn, kube-system/prometheus-to-sd-96fdn
- daemonset 이 존재 하는 노드일 경우 옵션 추가 해서 drain 시킴
kubectl drain gke-cluster-1-default-pool-20e07d73-8q3g --ignore-daemonsets
- drian 확인
kubectl get po -o wide
NAME READY STATUS RESTARTS AGE IP NODE
NOMINATED NODE READINESS GATES
nginx-84569d7db5-8qrd2 1/1 Running 0 59s 10.4.2.7 gke-cluster-1-default-pool-20e07d73-6mr
8 <none> <none>
nginx-84569d7db5-d7cgg 1/1 Running 0 8m20s 10.4.1.8 gke-cluster-1-default-pool-20e07d73-4ks
w <none> <none>
nginx-84569d7db5-gnbnq 1/1 Running 0 8m21s 10.4.1.9 gke-cluster-1-default-pool-20e07d73-4ks
w <none> <none>
nginx-84569d7db5-s6xsm 1/1 Running 0 59s 10.4.2.9 gke-cluster-1-default-pool-20e07d73-6mr
8 <none> <none>
–delete-local-data –force 등의 추가 옵션 있음
- uncordon
kubectl drain gke-cluster-1-default-pool-20e07d73-8q3g
17. Helm 차트 구성 및 사용(GCP 에서 수행)
17.1 Helm 차트 다운로드 및 설치
- 다운로드
curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3
chmod 700 get_helm.sh
./get_helm.sh
Downloading https://get.helm.sh/helm-v3.2.0-linux-amd64.tar.gz
Preparing to install helm into /usr/local/bin
helm installed into /usr/local/bin/helm
- 버전 확인
helm version
version.BuildInfo{Version:"v3.2.0", GitCommit:"e11b7ce3b12db2941e90399e874513fbd24bcb71", GitTreeState:"clean", GoVersion:"go1.13.10"}
- helm 차트 리포지토리 추가
helm repo add stable https://kubernetes-charts.storage.googleapis.com/
- 리포지토리 업데이트
helm repo update
Hang tight while we grab the latest from your chart repositories...
...Successfully got an update from the "stable" chart repository
Update Complete. ⎈ Happy Helming!⎈
17.2 mysql Helm 차트 다운로드 및 구성
- mysql helm 검색
helm search repo stable/mysql
NAME CHART VERSION APP VERSION DESCRIPTION
stable/mysql 1.6.3 5.7.28 Fast, reliable, scalable, and easy to use open-...
stable/mysqldump 2.6.0 2.4.1 A Helm chart to help backup MySQL databases usi...
- 피키지 메타 정보 보기
helm show chart stable/mysql
apiVersion: v1
appVersion: 5.7.28
description: Fast, reliable, scalable, and easy to use open-source relational database
system.
home: https://www.mysql.com/
icon: https://www.mysql.com/common/logos/logo-mysql-170x115.png
keywords:
- mysql
- database
- sql
maintainers:
- email: o.with@sportradar.com
name: olemarkus
- email: viglesias@google.com
name: viglesiasce
name: mysql
sources:
- https://github.com/kubernetes/charts
- https://github.com/docker-library/mysql
version: 1.6.3
- mysql helm 차트 설치 및 Deployment
helm install stable/mysql --generate-name
AME: mysql-1588321002
LAST DEPLOYED: Fri May 1 08:16:55 2020
NAMESPACE: default
STATUS: deployed
REVISION: 1
NOTES:
MySQL can be accessed via port 3306 on the following DNS name from within your cluster:
mysql-1588321002.default.svc.cluster.local
To get your root password run:
MYSQL_ROOT_PASSWORD=$(kubectl get secret --namespace default mysql-1588321701 -o jsonpath="{.data.mysql-root-password}" | base64 --decode; echo)
To connect to your database:
1. Run an Ubuntu pod that you can use as a client:
kubectl run -i --tty ubuntu --image=ubuntu:16.04 --restart=Never -- bash -il
2. Install the mysql client:
$ apt-get update && apt-get install mysql-client -y
3. Connect using the mysql cli, then provide your password:
$ mysql -h mysql-1588321701 -p
To connect to your database directly from outside the K8s cluster:
MYSQL_HOST=127.0.0.1
MYSQL_PORT=3306
# Execute the following command to route the connection:
kubectl port-forward svc/mysql-1588321002 3306
mysql -h ${MYSQL_HOST} -P${MYSQL_PORT} -u root -p${MYSQL_ROOT_PASSWORD}
helm ls
NAME NAMESPACE REVISION UPDATED STATUS C
HART APP VERSION
mysql-1588321701 default 1 2020-05-01 17:28:25.322363879 +0900 +09 deployed m
ysql-1.6.3 5.7.28
- helm 차스 uninstall
heml list
NAME NAMESPACE REVISION UPDATED STATUS C
HART APP VERSION
mysql-1588321701 default 1 2020-05-01 17:28:25.322363879 +0900 +09 deployed m
ysql-1.6.3 5.7.28
helm uninstall mysql-1588321701
release "mysql-1588321701" uninstalled
Istio 구성 하기
20. 최종 연습문제
20.1 PHP GuestBook with Redis
20.1.1 과제 개요
- 레디스 마스터 구성
- 레디스 슬레이브 구성
- Guestbook 프론트앤드 구성
- 프로트앤드 애플리케이션 서비스로 노출 시키기
- 삭제
20.1.2 레디스 마스터 Deployment 로 구성
항목 | 값 |
---|---|
파일명 | redis-master-deployment.yaml |
Deployment name | redis-master |
Deployment Label | app: redis |
deployment Selector / pod metadata | app: redis / role: master / tier: backend |
replica | 1 |
Image | k8s.gcr.io/redis:e2e |
Port | 6379 |
kubectl logs -f POD-NAME
20.1.3 레디스 마스터 서비스 구성
항목 | 값 |
---|---|
Type | ClusterIP |
Service 이름 | redis-master |
Service Label | app: redis / role: master / tier: backend |
port / targetPort | 6379 / 6379 |
selector | app: redis / role: master / tier: backend |
20.1.4 레디스 슬레이브 Deployment 구성
항목 | 값 |
---|---|
파일명 | redis-slave-deployment.yaml |
Deployment Name | redis-slave |
Deployment Label | app: redis |
Deployment matchLabel | app: redis / role: slave / tier: backend |
Replicas : 2 | |
Pod Label | app: redis / role: slave / tier: backend |
Container name | slave |
Image | gcr.io/google_samples/gb-redisslave:v3 |
환경변수 : GET_HOSTS_FROM | 마스터 노드의 주소로 지정 하되 value=dns 로 설정 |
containerPort | 6379 |
- 아래와 같이 소스 코드를 보면 GET_HOSTS_FROM 에는 master 의 주소가 들어가야함
$host = 'redis-master';
if (getenv('GET_HOSTS_FROM') == 'env') {
$host = getenv('REDIS_MASTER_SERVICE_HOST');
}
20.1.5 레디스 슬레이브 서비스 구성
항목 | 값 |
---|---|
Type | ClusterIP |
Service 이름 | redis-slave |
Service Label | app: redis / role: slave / tier: backend |
port / targetPort | 6379 / 6379 |
selector | app: redis / role: slaver / tier: backend |
20.1.6 GuestBook 애플리케이션 Deployment 생성
항목 | 값 |
---|---|
파일명 | frontend-deployment.yaml |
Deployment Name | frontend |
Deployment Label | app: guestbook |
Deployment matchLabel | app: guestbook / tier: frontend |
Replicas : 3 | |
Pod Label | app: guestbook / tier: frontend |
Container name | php-redis |
Image | gcr.io/google-samples/gb-frontend:v4 |
환경변수 : GET_HOSTS_FROM | 마스터 노드의 주소로 지정 하되 value=dns 로 설정 |
containerPort | 80 |
20.1.7 GuestBook 애플리케이션 LoadBalancer 서비스 구성
항목 | 값 |
---|---|
Service name | frontend |
service Label | app: guestbook / tier: frontend |
Type | LoadBalancer |
Port | 80 |
selector | app: guestbook / tier: frontend |
20.1.8 FrontEnd 앱 스케일링 해보기
replica 를 5개로 스케일링 해보기
21. Kata 연습 문제
####
1. 단일 Pod 생성
prodnamespace 라는 이름으로 네임스페이스를 만들고 해당 네임스페이스 내에 nginx 단일 Pod 를 생성하세요 (명령어로)
kubectl create namespace prodnamespace
kubectl run nginx --image=nginx -n prodnamespace
2. 명령어 이용 다중 Pod 생성
nginx:1.7.9 이미지로 복제본이 2개이고 컨테이너 포트가 80으로 개방된 nginx 라는 이름의 Deployment 를 생성 하세요
kubectl run nginx-deployment --image=nginx:1.7.8 --replicas=2 --port=80
2.1 하나의 Pod 를 선택해서 yaml 파일을 출력하세요
kubectl get po
kubectl get po nginx-8bfd472d32-gjzp8 -o yaml
2.2 nginx 이미지를 1.7.9 로 업데이트 하고, 업데이트 내용의 이력을 남기세요 (–record)
kubectl set image deploy nginx-deployment nginx-deployment=nginx:1.7.9 --record
혹은
kubectl edit deploy nginx-deloyment
2.3 nginx 1.7.9 에서 에러가 발생 했다고 가정하고 rollback 하세요
kubectl rollout undo deployment/nginx-deployment
2.4 rollout 히스토리를 확인 하세요
kubectl rollout history deployment/nginx-deployment
2.5 rivision 번호를 이용해 1.7.9 로 rollout undo 하세요
kubectl rollout undo deployment/nginx-deployment --to-revision=2
2.6 nginx Pod 에 app=v1 이라는 라벨을 입력 하세요
kubectl label deploy nginx-deployment app=v1
3. BGD(Blue Green Deployment) 구현하기
3.1 nginx 앱을 로드밸런싱 해줄 Loadbalancer 를 구현 하세요
apiVersion: v1
kind: Service
metadata:
name: nginx-lb
spec:
selector:
app: v1
ports:
- protocol: TCP
port: 80
targetPort: 80
type: LoadBalancer
3.2 nginx 의 Loadbalancer External-IP 를 확인하고 curl 명령어로 테스트 해보세요
kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.8.0.1 <none> 443/TCP 30h
nginx-lb LoadBalancer 10.8.7.22 35.184.195.100 80:30833/TCP 38s
curl http://35.184.195.100
Appendix
Appendix 0. VirtualBox 이미지 구성
1. VirtualBox 다운로드 및 설치
다운로드 : https://www.virtualbox.org/wiki/Downloads
2. 가상 이미지 가져오기
- 구글 드라이버 URL
https://drive.google.com/open?id=1qAv-FyIWbQVIxNn3MKfjIwbVdvo4rxVl
3. 가상 이미지 가져오기
버추얼 박스 실행 후에 파일 > 가상이미지 가져오기 클릭
4. VM 설정hisotyr
vm 이름, CPU 개수, MAC 주소 정책 을 아래와 같이 수정 합니다.
5. VM 복제
오른쪽마우스 -> 복제 클릭
VM이름 및 MAC주소정책 변경 후 복제 클릭
동일한 방법으로 worker02 VM 또 생성 합니다. 최종적으로 아래와 같이 3개의 VM 이 보이면 됩니다.
복제된 vm 에 접속하여 /etc/netplan/00-installer-config.yaml 파일을 수정 합니다.
network:
ethernets:
enp0s3:
dhcp4: no
addresses: [10.0.2.17/24] ## IP 수정 (VM 마다 하나씩 IP 증가)
gateway4: 10.0.2.2
nameservers:
addresses: [8.8.8.8, 8.8.4.4]
enp0s8:
dhcp4: no
addresses: [192.168.56.110/24] ## IP 수정 (VM 마다 하나씩 IP 증가)
version: 2
수정 후에는 netplan 명령어로 변경된 IP 로 적용
netplan apply
Appendix 1. 쿠버네티스 설치
1.설치 사전 작업
1.1 Nftable disable
sudo update-alternatives --set iptables /usr/sbin/iptables-legacy
sudo update-alternatives --set ip6tables /usr/sbin/ip6tables-legacy
sudo update-alternatives --set arptables /usr/sbin/arptables-legacy
sudo update-alternatives --set ebtables /usr/sbin/ebtables-legacy
1.2 호스트명 변경
# hostnamectl set-hostname [FQDN-HOST-NAME] --static
# 마스터 노드에서 수행
hostnamectl set-hostname kmaster
hostnamectl set-hostname kmaster.acorn.com --static
# 첫번째 Worker 노드에서 수행
hostnamectl set-hostname kworker01
hostnamectl set-hostname kworker01.acorn.com --static
# 두번째 Worker 노드에서 수행
hostnamectl set-hostname kworker02
hostnamectl set-hostname kworker02.acorn.com --static
1.3 각노드에 호스트 파일 등록
모든노드의 /etc/hosts 파일에 아래와 같이 등록 되어 있을것
192.168.56.111 kmaster.acorn.com kmaster
192.168.56.112 kworker01.acorn.com kworker01
192.168.56.113 kworker02.acorn.com kworker02
1.4 방화벽 점검
1.4.1 Control Plane 노드
Protocol | Direction | Port Range | Purpose | Used By |
---|---|---|---|---|
TCP | Inbound | 6443* | Kubernetes API server | All |
TCP | Inbound | 2379-2380 | etcd server client API | kube-apiserver, etcd |
TCP | Inbound | 10250 | Kubelet API | Self, Control plane |
TCP | Inbound | 10251 | kube-scheduler | Self |
TCP | Inbound | 10252 | kube-controller-manager | Self |
1.4.2 worker 노드
Protocol | Direction | Port Range | Purpose | Used By |
---|---|---|---|---|
TCP | Inbound | 10250 | Kubelet API | Self, Control plane |
TCP | Inbound | 30000-32767 | NodePort Services** | All |
2. Runtime 설치
2.1 도커 설치 (all nodes)
sudo apt update
sudo apt install docker.io
2.2 kubernetes 설치 (all nodes)
설치 스크립트 클릭
sudo apt-get update && sudo apt-get install -y apt-transport-https curl
curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add -
cat <<EOF | sudo tee /etc/apt/sources.list.d/kubernetes.list
deb https://apt.kubernetes.io/ kubernetes-xenial main
EOF
sudo apt-get update
sudo apt-get install -y kubelet kubeadm kubectl
sudo apt-mark hold kubelet kubeadm kubectl
3. Post Installation
3.1 SWAP 기능 해제(all nodes)
sudo swapoff -a # 현재 일시적용
sudo sed -i '/swap/s/^/#/' /etc/fstab # 재가동 후에도 swapoff 할려면 수행 해야함
3.2 도커 시스템서비스 등록 하기 (all nodes)
도커 데몬을 system 서비스에 등록하지 않으면 kubernetes 설치시에 warning 발생 하기 때문에 아래와 같이 등록해줌
sudo vi /etc/docker/daemon.json
아래와 같이 입력 후 저장 합니다.
{
"exec-opts": ["native.cgroupdriver=systemd"],
"log-driver": "json-file",
"log-opts": {
"max-size": "100m"
},
"storage-driver": "overlay2"
}
sudo mkdir -p /etc/systemd/system/docker.service.d
# Restart docker.
sudo systemctl enable docker.service
sudo systemctl daemon-reload
sudo systemctl restart docker
3.3 kubeadm을 사용하여 마스터 설정 (master node)
네트워크 인터페이스가 여러개일 경우 가장 우선 순위가 가장 높은 인터페이스가 자동 선정 되기 때문에 ‘–apiserver-advertise-address' 옵션을 사용해서 ip 혹은 인터페이스 명을 지정해야 합니다.
sudo kubeadm init --pod-network-cidr=192.168.0.0/16 --service-cidr 10.96.0.0/12 --apiserver-advertise-address=192.168.56.111
# kubeadmin init 시에 여러 가지 옵션들
# --pod-network-cidr=192.168.0.0/16
# --control-plane-endpoint=192.168.56.111
# --apiserver-cert-extra-sans=192.168.56.111
# --service-cidr 10.96.0.0/12
# --service-dns-domain "k8s"
# --apiserver-advertise-address __YOUR_IP_HERE___
# 잘못 설치한 경우 master 및 worker 노드에 수행 하면 모든 설정을 초기화함
# kubeadm reset cleanup-node
4. 워커 노드 등록
4.1 워커 노드 등록 (worker node only)
반듯이 kubeadm init 을 통해 나온 로그에 표시된 ip 와 token 으로 worker 노드에서만 수행
sudo kubeadm join 192.168.56.111:6443 --token dro5or.x9ujk49k0aadiz8s \
--discovery-token-ca-cert-hash sha256:b6372f30c5733a5c88d0a6b6095efbf4cb495329cbcd19df33e7a894a96ec53d
4.2 마스터 노드 kube client 설정 (master node)
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
4.3 클러스터 상태 확인(master node)
결과가 모두 not ready 로 나옴 (시간이 좀 걸림)
kubectl get nodes
4.4 네트워크 어플리케이션 설치(master node)
네트워크 툴 설치 후에는 모든 노드가 ready 로 나와야 함
kubectl apply -f "https://cloud.weave.works/k8s/net?k8s-version=$(kubectl version | base64 | tr -d '\n')"
kubectl get nodes
4.5 kubectl 명령어 자동완성 패키지 설치(master node)
# 자동 완성을 bash 셸에 영구적으로 추가한다
echo "# k8s auto completion and alias" >> ~/.bashrc
echo "source <(kubectl completion bash)" >> ~/.bashrc
echo "alias k=kubectl" >> ~/.bashrc
echo "complete -F __start_kubectl k" >> ~/.bashrc
5. etcd 설치(master node)
기본적으로 내장 etcd 가 있지만, etcd-io 의 릴리즈로 설치 합니다.
다운로드 url : 클릭
wget https://github.com/etcd-io/etcd/releases/download/v3.3.18/etcd-v3.3.18-linux-amd64.tar.gz
tar -xf etcd-v3.3.18-linux-amd64.tar.gz
cd etcd-v3.3.18-linux-amd64
sudo ETCDCTL_API=3 ./etcdctl --endpoints 127.0.0.1:2379 \
--cacert /etc/kubernetes/pki/etcd/ca.crt \
--cert /etc/kubernetes/pki/etcd/server.crt \
--key /etc/kubernetes/pki/etcd/server.key \
get / --prefix --keys-only
Appendix 2. 구글 GKE 사용하기
1. 회원가입
- $300 무료 크레딧 제공
- 신용카드 필요 (한도를 넘으도 자동 과금 안됨)
- http://cloud.google.com 에서 회원 가입
2. 프로젝트 생성
- 프로젝트 선택 을 클릭 합니다.
- 새 프로젝트 를 클릭 합니다.
- 프로젝트 이름에 원하는 값을 입력하고 만들기 클릭
3. 쿠버네티스 클러스터 생성
- 홈메뉴 에서 Kubernetes Engine 클릭
- 프로젝트를 선택하기 위해 프로젝트 선택 클릭
- 팝업창이 뜨면 프로젝트 gke-first 를 선택하고 열기 클릭
- 1분정도 기다린 후에 클러스터 만들기 클릭
- 클러스터 기본사항 에서 영역을 "asia-east1-a" 로 선택 한후, 만들기 클릭
- 아래와 같이 k8s 클러스터를 생성 중인 화면이 나오면 정상 적으로 진행이 된 것입니다.
4. 쿠버네티스 클러스터 접속 테스트
- GKE 클러스터가 생성되면 연결 클릭
- 팝업창이 뜨면 Cloud Shell에서 실행 클릭
Appendix 4. Google Cloud SDK 설치 하기
1. GCloud SDK 다운로드
2. Cloud SDK 설치
3. 로컬 머신에서 Cloud Shell 연결 명령어 복사
4. 로컬 CMD 또는 SHELL 에서 연결 하기
웹에서 복사한 내용을 그대로 붙여놓고 실행
Appendix 3. Git 계정 생성 및 Sync
1.Git 계정생성
www.github.com 에서 계정 생성
2. Git 리포지토리 생성
- GitHub.com 에 자신의 계정으로 로그인하여 아래 화면과 같이 리포지토리 생성
- 리포지토리 이름을 아래와 같이 입력하고. 생성 합니다. (Repository name : k8s-web)
3. 소스 파일 작성
$ mkdir -p ./gitvolumn/html
$ mkdir -p ./gitvolumn/kubetmp
$ cd ./gitvolumn/html
$ vi index.html
index.html 이름으로 아래 페이지를 작성 합니다.
<!DOCTYPE html>
<html>
<body>
<h1>K8s Landing Page</h1>
<p>Hello Kubernetes !!!</p>
</body>
</html>
4. Git 리포지토리 생성 및 초기화
$ git init
$ git add .
$ git commit -a -m "first commit"
$ git remote add origin https://github.com/<계정명>/k8s-web.git
$ git remote -v
$ git push origin master
$ git status
Appendix 4. Persist Volume 서비스를 위한 Ceph 설치
1. Ceph 설치(worker01, worker02)
$ apt-cache search ceph
$ apt install ceph