CRD를 통한 사용자 정의 컨트롤러의 예 소개
이 항목은 사용자 정의 리소스 정의(CRD)를 사용하여 사용자 정의 컨트롤러를 구현하는 예시를 설명합니다.실시 예로 당사 내에서 개발·이용하는 Etcd as a 서비스의 개요와 구조를 소개합니다.
Etcd as a Service
이 항목은 Etcd asa 서비스를 하나의 명령을 통해 etcd 집단을 구축하고 그 집단을 관리하는 서비스로 정의합니다.
당사가 개발하고 사용하는 Etcd as a 서비스는 다음과 같은 기능을 가지고 있습니다.
구현 방법
Etcd as a 서비스를 주로 처리하는 사용자 정의 자원과 사용자 정의 컨트롤러는 etcd와 Machine 두 가지로 나뉜다.
etcd는 etcd 군집을 나타내는 자원입니다. etcd 자원을 만들면 etcd 컨트롤러가 etcd 군집을 만들고 관리합니다.
Machine은 CloudProvider(예를 들어 OpenStack)가 제공하는 실례(예를 들어 VM)에 대한 추상적인 자원입니다. Machine 컨트롤러는 Machine 자원을 만든 후에 Machine 컨트롤러는 CloudProvider에서 실례를 만들고 관리합니다.
개발한 사용자 정의 컨트롤러는 작년Kubernetes Meetup Tokyo#3에 소개된 Kubernetes as a 서비스 때의 실현 방법과 같이 다음과 같은 Kubernetes의 구조를 이용하여 실현한다.
etcd군집의 창설 처리 자체는 StatefullSets와 같은 일반적인 방식이 아니라 CoreOS의etcd-operator를 참고하여 컨트롤러 측면에서 etcd의memer의 추가 처리를 실시하는 등 전용 컨트롤러를 창설하여 군집을 만든다.Machine 컨트롤러는 Kubernetes as a Service를 직접 사용할 때 제작된 컨트롤러입니다.
실행 예
나는 문장만으로는 이해하기 어렵다고 생각해서 실제로 Etcd as a 서비스를 사용한다.
먼저 클러스터를 생성합니다.클러스터를 만들려면 CRD 리소스 목록을 준비하십시오.이번 제작 선언은
sample-etcd.yamlapiVersion: external.zlab.co.jp/v1alpha1
kind: Etcd
metadata:
name: sample-etcd
spec:
version: 3.0.17
replicas: 3
backupPolicy:
backupIntervalInSeconds: 3600
maxBackups: 5
machineFlavor: large
machineImageName: container-linux-1465-8-0
machinePoolName: development
kubectl로 이 목록을 적용합니다.$ kubectl apply -f sample-etcd.yaml
etcd "sample-etcd" created
자원을 만들면 이 그룹에 배치된 사용자 정의 컨트롤러가 자원의 생성을 감지하고 etcd 그룹을 만들기 시작합니다.
etcd 컨트롤러는 클러스터를 만들기 위해 인증서를 생성하거나 DNS를 등록한 다음 Machine 리소스를 생성합니다.
클러스터를 생성하는 Machine 리소스의 상태를 확인합니다.$ kubectl get machine -o json | jq -c '.items[]|{"name": .metadata.name, "status": .status.phase, "ip": .status.machineState.hostIP }'
{"name":"1-sample-etcd-default","status":"Creating","ip":"182.22.23.11"}
이렇게 하면 etcd 컨트롤러는 Machine 자원을 군집을 만드는 처리로 사용합니다. 이것은 Machine를 만드는 것을 볼 수 있습니다.Phase가 런닝이면 Machine 제작이 완료됩니다.
기계가 실행될 때, etcd 컨트롤러는 다음 기계를 만들 것입니다.$ kubectl get m -o json | jq -c '.items[]|{"name": .metadata.name, "status": .status.phase, "ip": .status.machineState.hostIP }'
{"name":"1-sample-etcd-default","status":"Error","ip":"182.22.23.11"}
{"name":"2-sample-etcd-default","status":"Creating","ip":"182.22.23.17"}
두 번째 제작이 시작되었다.여기서 완성해야 할 1-sample-etcd-default의 Phase는 Error입니다. 이것은 etcd의 member를 추가했기 때문입니다. status의ready 구성원이 절반 이하를 초과하고 etcd의health는false를 되돌려줍니다.$ kubectl get m -o json | jq -c '.items[]|{"name": .metadata.name, "status": .status.phase, "ip": .status.machineState.hostIP }'
{"name":"1-sample-etcd-default","status":"Running","ip":"182.22.23.11"}
{"name":"2-sample-etcd-default","status":"Running","ip":"182.22.23.17"}
{"name":"3-sample-etcd-default","status":"Creating","ip":"182.22.23.18"}
위에서 말한 바와 같이 만약에 2-sample-etcd-default가 런닝이라면 1-sample-etcd-default도 런닝이다.
replicas를 3으로 설정하기 때문에 3-sample-etcd-default가 실행되면 군집 생성이 완료되고 etcd 자원의 Phase가 실행됩니다.$ kubectl get e sample-etcd -o yaml
apiVersion: external.zlab.co.jp/v1alpha1
kind: Etcd
metadata:
...
spec:
...
status:
clientCertificate:
secretName: sample-etcd-client-cert
endpoints:
- https://1.sample-etcd.default.etcd.sample.zlab.co.jp:2379
- https://2.sample-etcd.default.etcd.sample.zlab.co.jp:2379
- https://3.sample-etcd.default.etcd.sample.zlab.co.jp:2379
lastBackupTime: 2017-12-06T16:26:12Z
peerCertificate:
secretName: sample-etcd-peer-cert
phase: Running
ready: true
replicas: 3
serverCertificate:
secretName: sample-etcd-server-cert
storedBackupObjects:
- default/sample-etcd/2017-12-05T08:22:30Z
- default/sample-etcd/2017-12-06T15:26:11Z
- default/sample-etcd/2017-12-06T16:26:12Z
그럼 집단이 생겼으니 방문해보세요.
생성된 클러스터에 사용되는 각 인증서는 Secret 리소스로 저장되므로 클라이언트 인증서를 가져오고 연결합니다.$ kubectl get secret sample-etcd-client-cert -o json | jq -r '.data["certificate"]' | base64 -d > etcd-client.pem
$ kubectl get secret sample-etcd-client-cert -o json | jq -r '.data["private-key"]' | base64 -d > etcd-client.key
$ export ETCDCTL_API=3
# status.endpoints にある値を endpoints として利用する
$ export ETCD_ENDPOINTS=https://1.sample-etcd.default.etcd.sample.zlab.co.jp:2379,https://2.sample-etcd.default.etcd.sample.zlab.co.jp:2379,https://3.sample-etcd.default.etcd.sample.zlab.co.jp:2379
$ etcdctl --cert etcd-client.pem --key etcd-client.key --endpoints $ETCD_ENDPOINTS endpoint status
https://1.sample-etcd.default.etcd.sample.zlab.co.jp:2379, 6f3636672576c0f2, 3.0.17, 33 kB, true, 19, 33351
https://2.sample-etcd.default.etcd.sample.zlab.co.jp:2379, b9017e59944282a8, 3.0.17, 33 kB, false, 19, 33353
https://3.sample-etcd.default.etcd.sample.zlab.co.jp:2379, ab5b60a8ad3eaa09, 3.0.17, 33 kB, false, 19, 33354
값을 써보십시오.$ etcdctl --cert etcd-client.pem --key etcd-client.key --endpoints $ETCD_ENDPOINTS put /zlab "We are hiring!"
OK
$ etcdctl --cert etcd-client.pem --key etcd-client.key --endpoints $ETCD_ENDPOINTS get /zlab
/zlab
We are hiring!
이렇게 하면 일반적으로 etcd로 사용할 수 있다.
그리고 etcd 버전을 v3.2.11로 업그레이드해 보십시오.
다음과 같이 목록을 수정합니다.
sample-etcd.yamlspec:
+ version: 3.2.11
- version: 3.0.17
replicas: 3
수정된 목록입니다.$ kubectl apply -f sample-etcd.yaml
etcd "sample-etcd" configured
응용 프로그램이 자원 변경을 감지하고 스크롤 업데이트를 시작합니다.
스크롤 업데이트도 당연하지만 etcd는 정상적으로 사용할 수 있습니다.$ kubectl get m -o json | jq -c '.items[]|{"name": .metadata.name, "status": .status.phase, "ip": .status.machineState.hostIP }'
{"name":"1-sample-etcd-default","status":"Creating","ip":"182.22.22.77"}
{"name":"2-sample-etcd-default","status":"Running","ip":"182.22.22.44"}
{"name":"3-sample-etcd-default","status":"Running","ip":"182.22.22.45"}
$ etcdctl --cert etcd-client.pem --key etcd-client.key --endpoints $ETCD_ENDPOINTS get /zlab
/zlab
We are hiring!
업데이트가 완료되면 v3.2.11이 표시됩니다.$ etcdctl --cert etcd-client.pem --key etcd-client.key --endpoints $ETCD_ENDPOINTS endpoint status
https://1.sample-etcd.default.etcd.sample.zlab.co.jp:2379, 6f3636672576c0f2, 3.2.11, 33 kB, true, 19, 33351
https://2.sample-etcd.default.etcd.sample.zlab.co.jp:2379, b9017e59944282a8, 3.2.11, 33 kB, false, 19, 33353
https://3.sample-etcd.default.etcd.sample.zlab.co.jp:2379, ab5b60a8ad3eaa09, 3.2.11, 33 kB, false, 19, 33354
그런 다음 페일오버를 시도합니다.
세 개의 Stack 열기 인스턴스 중 하나가 고장으로 인해 다운되었다고 가정합니다.$ kubectl get m -o json | jq -c '.items[]|{"name": .metadata.name, "status": .status.phase, "ip": .status.machineState.hostIP }'
{"name":"1-sample-etcd-default","status":"Running","ip":"182.22.22.77"}
{"name":"2-sample-etcd-default","status":"Error","ip":"182.22.22.44"}
{"name":"3-sample-etcd-default","status":"Running","ip":"182.22.22.45"}
그러면 해당 Machine 리소스의 Probe가 실패하므로 Phase가 Error가 됩니다.이 상태가 일정 시간 이상 지속되면 etcd 컨트롤러는 Error의 컴퓨터를 삭제하고 다시 생성합니다.kubectl get m -o json | jq -c '.items[]|{"name": .metadata.name, "status": .status.phase, "ip": .status.machineState.hostIP }'
{"name":"1-sample-etcd-default","status":"Running","ip":"182.22.22.77"}
{"name":"2-sample-etcd-default","status":"Creating","ip":"182.22.22.85"}
{"name":"3-sample-etcd-default","status":"Running","ip":"182.22.22.45"}
따라서 이렇게 자동으로 복구됩니다.
마지막으로 배율을 조정합니다.나는 etcd가 축소를 잘 하지 않는다고 생각하지만, 이번에는 리플리카스를 3에서 5로 변경할 것이다.
sample-etcd.yamlspec:
version: 3.2.11
+ replicas: 5
- replicas: 3
$ kubectl apply -f sample-etcd.yaml
etcd "sample-etcd" configured
군집을 만들 때처럼 하나하나 추가하여 최종적으로 리플렉스 수량의 5개로 수렴합니다.$ kubectl get m -o json | jq -c '.items[]|{"name": .metadata.name, "status": .status.phase, "ip": .status.machineState.hostIP }'
{"name":"1-sample-etcd-default","status":"Running","ip":"182.22.22.77"}
{"name":"2-sample-etcd-default","status":"Running","ip":"182.22.22.85"}
{"name":"3-sample-etcd-default","status":"Running","ip":"182.22.22.45"}
{"name":"4-sample-etcd-default","status":"Running","ip":"182.22.22.81"}
{"name":"5-sample-etcd-default","status":"Creating","ip":"182.22.22.94"}
총결산
이번에는 CRD를 이용한 사용자 정의 컨트롤러의 설치 사례 중 하나로 당사에서 개발·이용하는 Etcd as a 서비스를 소개합니다.자세한 내용이 다 기재되지 않으니 관심 있으시면 Kubernetes Meetup Tokyo 등 직접 물어보시면 됩니다.
CRD와 사용자 정의 컨트롤러를 사용하면 Kubernetes를 확장할 수 있고 다양한 일을 할 수 있습니다.며칠 전 진행된 KubeCon 2017 에서도 CRD와 사용자 정의 컨트롤러(Operator)를 사용한 이야기가 몇 개 있었기 때문에 Z Lab Advent Calendar 2017 21일 항목에서 몇 개를 소개할 예정이다.가능하다면 저쪽을 보세요.
참고 문헌
apiVersion: external.zlab.co.jp/v1alpha1
kind: Etcd
metadata:
name: sample-etcd
spec:
version: 3.0.17
replicas: 3
backupPolicy:
backupIntervalInSeconds: 3600
maxBackups: 5
machineFlavor: large
machineImageName: container-linux-1465-8-0
machinePoolName: development
$ kubectl apply -f sample-etcd.yaml
etcd "sample-etcd" created
$ kubectl get machine -o json | jq -c '.items[]|{"name": .metadata.name, "status": .status.phase, "ip": .status.machineState.hostIP }'
{"name":"1-sample-etcd-default","status":"Creating","ip":"182.22.23.11"}
$ kubectl get m -o json | jq -c '.items[]|{"name": .metadata.name, "status": .status.phase, "ip": .status.machineState.hostIP }'
{"name":"1-sample-etcd-default","status":"Error","ip":"182.22.23.11"}
{"name":"2-sample-etcd-default","status":"Creating","ip":"182.22.23.17"}
$ kubectl get m -o json | jq -c '.items[]|{"name": .metadata.name, "status": .status.phase, "ip": .status.machineState.hostIP }'
{"name":"1-sample-etcd-default","status":"Running","ip":"182.22.23.11"}
{"name":"2-sample-etcd-default","status":"Running","ip":"182.22.23.17"}
{"name":"3-sample-etcd-default","status":"Creating","ip":"182.22.23.18"}
$ kubectl get e sample-etcd -o yaml
apiVersion: external.zlab.co.jp/v1alpha1
kind: Etcd
metadata:
...
spec:
...
status:
clientCertificate:
secretName: sample-etcd-client-cert
endpoints:
- https://1.sample-etcd.default.etcd.sample.zlab.co.jp:2379
- https://2.sample-etcd.default.etcd.sample.zlab.co.jp:2379
- https://3.sample-etcd.default.etcd.sample.zlab.co.jp:2379
lastBackupTime: 2017-12-06T16:26:12Z
peerCertificate:
secretName: sample-etcd-peer-cert
phase: Running
ready: true
replicas: 3
serverCertificate:
secretName: sample-etcd-server-cert
storedBackupObjects:
- default/sample-etcd/2017-12-05T08:22:30Z
- default/sample-etcd/2017-12-06T15:26:11Z
- default/sample-etcd/2017-12-06T16:26:12Z
$ kubectl get secret sample-etcd-client-cert -o json | jq -r '.data["certificate"]' | base64 -d > etcd-client.pem
$ kubectl get secret sample-etcd-client-cert -o json | jq -r '.data["private-key"]' | base64 -d > etcd-client.key
$ export ETCDCTL_API=3
# status.endpoints にある値を endpoints として利用する
$ export ETCD_ENDPOINTS=https://1.sample-etcd.default.etcd.sample.zlab.co.jp:2379,https://2.sample-etcd.default.etcd.sample.zlab.co.jp:2379,https://3.sample-etcd.default.etcd.sample.zlab.co.jp:2379
$ etcdctl --cert etcd-client.pem --key etcd-client.key --endpoints $ETCD_ENDPOINTS endpoint status
https://1.sample-etcd.default.etcd.sample.zlab.co.jp:2379, 6f3636672576c0f2, 3.0.17, 33 kB, true, 19, 33351
https://2.sample-etcd.default.etcd.sample.zlab.co.jp:2379, b9017e59944282a8, 3.0.17, 33 kB, false, 19, 33353
https://3.sample-etcd.default.etcd.sample.zlab.co.jp:2379, ab5b60a8ad3eaa09, 3.0.17, 33 kB, false, 19, 33354
$ etcdctl --cert etcd-client.pem --key etcd-client.key --endpoints $ETCD_ENDPOINTS put /zlab "We are hiring!"
OK
$ etcdctl --cert etcd-client.pem --key etcd-client.key --endpoints $ETCD_ENDPOINTS get /zlab
/zlab
We are hiring!
spec:
+ version: 3.2.11
- version: 3.0.17
replicas: 3
$ kubectl apply -f sample-etcd.yaml
etcd "sample-etcd" configured
$ kubectl get m -o json | jq -c '.items[]|{"name": .metadata.name, "status": .status.phase, "ip": .status.machineState.hostIP }'
{"name":"1-sample-etcd-default","status":"Creating","ip":"182.22.22.77"}
{"name":"2-sample-etcd-default","status":"Running","ip":"182.22.22.44"}
{"name":"3-sample-etcd-default","status":"Running","ip":"182.22.22.45"}
$ etcdctl --cert etcd-client.pem --key etcd-client.key --endpoints $ETCD_ENDPOINTS get /zlab
/zlab
We are hiring!
$ etcdctl --cert etcd-client.pem --key etcd-client.key --endpoints $ETCD_ENDPOINTS endpoint status
https://1.sample-etcd.default.etcd.sample.zlab.co.jp:2379, 6f3636672576c0f2, 3.2.11, 33 kB, true, 19, 33351
https://2.sample-etcd.default.etcd.sample.zlab.co.jp:2379, b9017e59944282a8, 3.2.11, 33 kB, false, 19, 33353
https://3.sample-etcd.default.etcd.sample.zlab.co.jp:2379, ab5b60a8ad3eaa09, 3.2.11, 33 kB, false, 19, 33354
$ kubectl get m -o json | jq -c '.items[]|{"name": .metadata.name, "status": .status.phase, "ip": .status.machineState.hostIP }'
{"name":"1-sample-etcd-default","status":"Running","ip":"182.22.22.77"}
{"name":"2-sample-etcd-default","status":"Error","ip":"182.22.22.44"}
{"name":"3-sample-etcd-default","status":"Running","ip":"182.22.22.45"}
kubectl get m -o json | jq -c '.items[]|{"name": .metadata.name, "status": .status.phase, "ip": .status.machineState.hostIP }'
{"name":"1-sample-etcd-default","status":"Running","ip":"182.22.22.77"}
{"name":"2-sample-etcd-default","status":"Creating","ip":"182.22.22.85"}
{"name":"3-sample-etcd-default","status":"Running","ip":"182.22.22.45"}
spec:
version: 3.2.11
+ replicas: 5
- replicas: 3
$ kubectl apply -f sample-etcd.yaml
etcd "sample-etcd" configured
$ kubectl get m -o json | jq -c '.items[]|{"name": .metadata.name, "status": .status.phase, "ip": .status.machineState.hostIP }'
{"name":"1-sample-etcd-default","status":"Running","ip":"182.22.22.77"}
{"name":"2-sample-etcd-default","status":"Running","ip":"182.22.22.85"}
{"name":"3-sample-etcd-default","status":"Running","ip":"182.22.22.45"}
{"name":"4-sample-etcd-default","status":"Running","ip":"182.22.22.81"}
{"name":"5-sample-etcd-default","status":"Creating","ip":"182.22.22.94"}
이번에는 CRD를 이용한 사용자 정의 컨트롤러의 설치 사례 중 하나로 당사에서 개발·이용하는 Etcd as a 서비스를 소개합니다.자세한 내용이 다 기재되지 않으니 관심 있으시면 Kubernetes Meetup Tokyo 등 직접 물어보시면 됩니다.
CRD와 사용자 정의 컨트롤러를 사용하면 Kubernetes를 확장할 수 있고 다양한 일을 할 수 있습니다.며칠 전 진행된 KubeCon 2017 에서도 CRD와 사용자 정의 컨트롤러(Operator)를 사용한 이야기가 몇 개 있었기 때문에 Z Lab Advent Calendar 2017 21일 항목에서 몇 개를 소개할 예정이다.가능하다면 저쪽을 보세요.
참고 문헌
Reference
이 문제에 관하여(CRD를 통한 사용자 정의 컨트롤러의 예 소개), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/shmurata/items/8bfbcfc5944ad57a6d43텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)