Hi, I'm Samina 👋

This is my Life & Technological Journey

Samina Website

Hi, I'm Samina 👋

This is my Life & Technological Journey

第一次玩 operator-sdk 就上手

5 minutes
February 4, 2019
Category:

文章脈絡

前言

在接觸 Kubernetes 一陣子後,會發現一堆 operators 。
而很殘念der,自己到目前都還沒有真正好好的玩過。
雖然在 operator-sdk 出現以前,有很多人都自己手刻 operator,不過既然 operator 目前都有個 Framework 了,當然就來玩它囉!

Operator Framework 是什麼

詳細的介紹請參閱:https://coreos.com/blog/introducing-operator-framework

認識 operator-sdk CLI

$ operator-sdk -h
An SDK for building operators with ease

Usage:
  operator-sdk [command]

Available Commands:
  add         Adds a controller or resource to the project
  build       Compiles code and builds artifacts
  completion  Generators for shell completions
  generate    Invokes specific generator
  help        Help about any command
  migrate     Adds source code to an operator
  new         Creates a new operator application
  olm-catalog Invokes a olm-catalog command
  print-deps  Print Golang packages and versions required to run the operator
  run         Runs a generic operator
  scorecard   Run scorecard tests
  test        Tests the operator
  up          Launches the operator

$ operator-sdk --version
operator-sdk version v0.4.0+git

本次會用到的指令就只有一個:operator-sdk new - 產生一個新的 operator 專案

實作開始

1. 建立 K8s 環境

Ref: https://github.com/operator-framework/operator-sdk#prerequisites

參考安裝:

2. 安裝 operator-sdk CLI

執行方式如下:

go get -u github.com/golang/dep/cmd/dep
go get -u github.com/operator-framework/operator-sdk
cd ~/go/src/github.com/operator-framework/operator-sdk
make dep
make install

3. 用 operator-sdk CLI 建立一個 operator

執行方式如下:

mkdir -p $GOPATH/src/github.com/<GitHub_ID>
cd $GOPATH/src/github.com/<GitHub_ID>
operator-sdk new <GitHub_Repo_Name>
cd <GitHub_Repo_Name>/

因為之後開發其他專案的關係,本次使用 helm 來練習。產生新專案的方式如下: operator-sdk new <project-name> --type=helm --kind=<kind> --api-version=<group/version>

如:

$ mkdir -p $GOPATH/src/github.com/sufuf3
$ cd $GOPATH/src/github.com/sufuf3
$ operator-sdk new play-k8s-operator --api-version=samina.fu.com/v1alpha1 --kind=MyTest --type helm
INFO[0000] Creating new Helm operator 'play-k8s-operator'.
INFO[0000] Create helm-charts/mytest/
INFO[0000] Create build/Dockerfile
INFO[0000] Create watches.yaml
INFO[0000] Create deploy/service_account.yaml
INFO[0000] Create deploy/role.yaml
INFO[0000] Create deploy/role_binding.yaml
INFO[0000] Create deploy/operator.yaml
INFO[0000] Create deploy/crds/samina_v1alpha1_mytest_crd.yaml
INFO[0000] Create deploy/crds/samina_v1alpha1_mytest_cr.yaml
INFO[0000] Run git init ...
Initialized empty Git repository in /home/vagrant/go/src/github.com/sufuf3/play-k8s-operator/.git/
INFO[0000] Run git init done
INFO[0000] Project creation complete.

跑完 operator-sdk new <project-name> --type=helm --kind=<kind> --api-version=<group/version>,進到資料夾中會發現它產生好的檔案,並且用 git log 會發現有一個 commit

$ cd play-k8s-operator/
$ tree
.
├── build
│   └── Dockerfile
├── deploy
│   ├── crds
│   │   ├── samina_v1alpha1_mytest_crd.yaml
│   │   └── samina_v1alpha1_mytest_cr.yaml
│   ├── operator.yaml
│   ├── role_binding.yaml
│   ├── role.yaml
│   └── service_account.yaml
├── helm-charts
│   └── mytest
│       ├── charts
│       ├── Chart.yaml
│       ├── templates
│       │   ├── deployment.yaml
│       │   ├── _helpers.tpl
│       │   ├── ingress.yaml
│       │   ├── NOTES.txt
│       │   ├── service.yaml
│       │   └── tests
│       │       └── test-connection.yaml
│       └── values.yaml
└── watches.yaml

$ git log
commit f0a174ce1deca8ef3b38c911b98b102ca7dfd27f
Author: Samina Fu <sufuf3@gmail.com>
Date:   Sat Feb 2 12:11:10 2019 +0000

    INITIAL COMMIT

4. 了解一下新產生的 helm operator 中的檔案

Ref: https://github.com/operator-framework/operator-sdk/blob/master/doc/helm/project_layout.md

從上面的檔案中會出現以下的資料夾和檔案:

5. 編輯檔案

1. watches.yaml

default 的 operator 會依據 watches.yaml 這個檔案來監控 我們自己定義的 kind 這個 resource 的事件。基本上,在我們執行 operator-sdk new 就已經依據我們定義的名稱產生好,所以這份檔案基本上不需要修改

---
- version: v1alpha1
  group: samina.fu.com
  kind: MyTest
  chart: /opt/helm/helm-charts/mytest

2. helm-charts

依自己喜好來編輯自己的 helm-charts 囉!
使用 helm install --name NAME --dry-run --debug ./helm-charts/mytest/ 來 debug。

參考:https://github.com/sufuf3/play-k8s-operator/blob/master/helm-dry-run.log

6. 先在 K8s 中 deploy CRD

kubectl create -f deploy/crds/GROUP_VERSION_CRDNAME_crd.yaml

eg.

kubectl create -f deploy/crds/samina_v1alpha1_mytest_crd.yaml

然后一个新的 RESTful API 就創建了:

$ curl -s https://172.17.8.100:6443/apis/samina.fu.com/v1alpha1/namespaces/*/mytests -k | jq
{
  "apiVersion": "samina.fu.com/v1alpha1",
  "items": [],
  "kind": "MyTestList",
  "metadata": {
    "continue": "",
    "resourceVersion": "233252",
    "selfLink": "/apis/samina.fu.com/v1alpha1/namespaces/*/mytests"
  }
}

7. Build operator container

可以依據官方提供的 Build 方式 operator-sdk build registry_name/username/image_name:v0.0.1 + docker push 來進行。 不過 operator 維護上,最好專注在 operator 的定義,至於 build docker 這件事情可以交給懶人法 - dockerhub 自動 Build。

eg.

8. 在 K8s 中部署 operator

1. 修改 deploy/operator.yaml 的 image 來源

sed -i 's|REPLACE_IMAGE|repository/username/images_name:version|g' deploy/operator.yaml

eg.

sed -i 's|REPLACE_IMAGE|sufuf3/my-operator-test:latest|g'  deploy/operator.yaml

2. 部署 operator

kubectl create -f deploy/service_account.yaml
kubectl create -f deploy/role.yaml
kubectl create -f deploy/role_binding.yaml
kubectl create -f deploy/operator.yaml

deploy 完後就可以看到我們的 operator 是 running 的

$ kubectl get deploy,pod
NAME                                      DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
deployment.extensions/play-k8s-operator   1         1         1            1           6m44s

NAME                                    READY   STATUS        RESTARTS   AGE
pod/play-k8s-operator-5c8fdc8fd-6m8tv   1/1     Running       0          6m44s

9. 在 K8s 中部署自己定義的 custom resource

編輯 deploy/crds/GROUP_VERSION_CRDNAME_cr.yaml 後 deploy。

在我未來的專案設計流程中,會是需要先自己 create 一個 namespace 後,再依據已經建立的 namespace ,建立自己的 resource。
以下就簡單的來用 default namespace 部署。

1. 編輯 deploy/crds/GROUP_VERSION_CRDNAME_cr.yaml

spec 底下就是自己定義的 values ,在我這個練習專案中,定義如下:

vim deploy/crds/samina_v1alpha1_mytest_cr.yaml

apiVersion: samina.fu.com/v1alpha1
kind: MyTest
metadata:
  name: example-mytest
spec:
  replicaCount: 1
  username: sufuf3
  containerName: mycontainer
  nameSpace: default
  image:
    repository: tensorflow/tensorflow
    tag: latest-jupyter
    pullPolicy: IfNotPresent
  nameOverride: ""
  fullnameOverride: ""
  service:
    type: NodePort
    port: 8888
    nodeport: 30566
  ingress:
    enabled: false
    annotations: {}
    paths: []
    hosts:
      - chart-example.local
    tls: []
  resources: {}
  nodeSelector: {}
  tolerations: []
  affinity: {}

2. 建立自己的 resource

kubectl create -f deploy/crds/samina_v1alpha1_mytest_cr.yaml

結果:

$ kubectl get all -l app=mytest
NAME                                                           READY   STATUS    RESTARTS   AGE
pod/example-mytest-6bxnrell81eqsmdueqsqy7l7z-798dc58c8-g8q8q   1/1     Running   0          5m46s

NAME                                               TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
service/example-mytest-6bxnrell81eqsmdueqsqy7l7z   NodePort   10.103.245.94   <none>        8888:30567/TCP   5m46s

NAME                                                       DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/example-mytest-6bxnrell81eqsmdueqsqy7l7z   1         1         1            1           5m46s

NAME                                                                 DESIRED   CURRENT   READY   AGE
replicaset.apps/example-mytest-6bxnrell81eqsmdueqsqy7l7z-798dc58c8   1         1         1       5m46s

透過 API:

$ curl -s https://172.17.8.100:6443/apis/samina.fu.com/v1alpha1/namespaces/default/mytests/example-mytest -k | jq

結語

本次的練習 GitHub repository 參考連結:https://github.com/sufuf3/play-k8s-operator

這樣透過 operator-framework/operator-sdk 要完成自己的 CRD 和 operator 真的很快速與方便,可以想見,如果是維運人員,了解需求後,可以不用寫很多的 operator 程式,就可以快速部署 operator 真的蠻便利的。且後續一樣可以很方便的使用 K8s 的 API。根本就是懶人救星。

不過,是否要使用 operator-framework/operator-sdk ,一切還是需要自行的評估是否合適自己,小心服用。

參考連結