概要・解説
Kubernetes Aggregated APIServerとは?
Kubernetesにはシステムコンポーネントとして、kube-apiserverがいますが、それとは別に独自に拡張したAggregated APIServerを配置することができます。
Custom ControllerのサンプルにSample Controllerがあるように、Custom APIServer(Aggregated APIServer)のサンプルとして公式リポジトリにSample APIServerがあります。
Sample Controllerの説明は下記で詳しく説明しているので、省略
https://nextpublishing.jp/book/11389.html
この記事は、そのSample APIServerの動かし方・遊び方についての記事です。
CRD(+Custom Controller)との違い
CRD + Custom Controllerを使ったOperatorが昨今のKubernetes界隈で流行っていますが、Aggregated APIServerはOperatorと比べると高い自由度を持つことができます。
CRDはある程度決められた枠組みの中で制作・使用することになりますが、APIServerはそれを超えた機能を実現できます。
Aggregated APIServerを使うことで何ができるのか? については
Programming Kubernetesの第8・9章に詳しくまとまっています
ただ、Aggregated APIServerを使わないと実現できないものはだいぶ限られます。
そのため、Kubernetesを拡張してなにかをしたい! という場合はほとんどCRD(+Custom Controller)の選択肢が主力になると思います。
実例も少ないため、Aggregated APIServerはマイナーといっていい存在です。
少なくとも日本語/英語含めて概要以外の記事が全くないので、この記事を書こうと思いました
Sample APIServerで遊ぶ
ここから本題です。Sample APIServerを動かす方法は二つあります。
- KubernetesクラスタにPodとしてSample APIServerをデプロイする
- Kubernetesクラスタに対して、etcdとSample APIServerをローカルプロセスとして動かす
この記事は2番目の方法の解説記事です。
ビルド
前提として、Golangのインストール・設定(Go Module含む)がされているものとします。
筆者の作業環境は下記です。下記のソフトウェアもインストール済みの前提で書いています。
- macOS 10.14.5
- Go 1.14.2
- Minikube v1.11.0
- etcd 3.3.11
Sample APIServerのソースをビルドします。
$ mkdir -p ~/go/src/k8s.io
$ git clone https://github.com/kubernetes/sample-apiserver.git
$ CGO_ENABLED=0 go build -a -o artifacts/simple-image/kube-sample-apiserver
準備する
Kubernetesクラスタを動かす
Kubernetesの拡張機能なので、当然Kubernetesクラスタが必要です。
今回はMinikubeを使って、ローカルクラスタを作ります。
$ minikube start --driver virtualbox
証明書を作る
Sample APIServerが利用する自己証明書を作成します。
- CA証明書
$ openssl req -nodes -new -x509 -keyout ca.key -out ca.crt
Generating a 2048 bit RSA private key
...........................................................+++
........................................+++
writing new private key to 'ca.key'
-----
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) []:JP
State or Province Name (full name) []:Tokyo
Locality Name (eg, city) []:Shibuya
Organization Name (eg, company) []:Kubernetes
Organizational Unit Name (eg, section) []:CA
Common Name (eg, fully qualified host name) []:development
Email Address []:
$ openssl req -out client.csr -new -newkey rsa:4096 -nodes -keyout client.key -subj "/CN=development/O=system:masters"
Generating a 4096 bit RSA private key
..................++
...........................++
writing new private key to 'client.key'
-----
- Client証明書
$ openssl x509 -req -days 365 -in client.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out client.crt
Signature ok
subject=/CN=development/O=system:masters
Getting CA Private Key
- curl用のp12形式
$ openssl pkcs12 -export -in ./client.crt -inkey ./client.key -out client.p12 -passout pass:password
Sample APIServerを起動する
etcdもローカルプロセスとして動かすため、インストールが必要です。
次のコマンドでetcdとSample APIServerを起動します。
$ etcd & ./artifacts/simple-image/kube-sample-apiserver \
--secure-port 8443 --etcd-servers http://127.0.0.1:2379 --v=7 \
--client-ca-file ca.crt --kubeconfig ~/.kube/config \
--authentication-kubeconfig ~/.kube/config --authorization-kubeconfig ~/.kube/config
ログが出てきたら起動完了です。
APISericeを動かして遊ぶ
このSample APIServerではKind: Flunder
というAPI Objectを扱います。
今回はローカルプロセスとして動かしているので、特に実行はしていませんが、通常はkind: APIService
を登録してからCustom API Obejectを作成します。
以下はAPIService
の参考です。
# https://github.com/kubernetes/sample-apiserver/blob/master/artifacts/example/apiservice.yaml
apiVersion: apiregistration.k8s.io/v1
kind: APIService
metadata:
name: v1alpha1.wardle.example.com
spec:
insecureSkipTLSVerify: true
group: wardle.example.com
groupPriorityMinimum: 1000
versionPriority: 15
service:
name: api
namespace: wardle
version: v1alpha1
どんなAPIServiceが他にあるのかを見たい人は、kubectl get apiservice
で見てみると楽しいかもしれません。
httpieインストール
macOSでSample APIServerと疎通するために、brewでhttpie
をインストールします。
$ brew install httpie
httpieでGET
Sample APIServerが動いているか確認するためにhttpie
でGETリクエストを投げてみます。
まだ何もAPI Objectを作ってないので、空のリストが返ってきます。
$ http --verify=no --cert client.crt --cert-key client.key \
https://localhost:8443/apis/wardle.example.com/v1alpha1/namespaces/default/flunders
HTTP/1.1 200 OK
Cache-Control: no-cache, private
Content-Length: 187
Content-Type: application/json
Date: Sat, 13 Jun 2020 12:19:43 GMT
{
"apiVersion": "wardle.example.com/v1alpha1",
"items": [],
"kind": "FlunderList",
"metadata": {
"resourceVersion": "2",
"selfLink": "/apis/wardle.example.com/v1alpha1/namespaces/default/flunders"
}
}
Sample APIServerをStandAloneで立てた状態でFlunder Objectを作るには、httpieを使ってPOSTリクエストを送ります。
$ echo '{ "apiVersion": "wardle.example.com/v1alpha1", "kind": "Flunder", "metadata": { "name": "my-first-flunder", "labels": { "sample-label": "true" } } }' | http --verify=no --cert client.crt --cert-key client.key https://localhost:8443/apis/wardle.example.com/v1alpha1/namespaces/default/flunders
HTTP/1.1 201 Created
Cache-Control: no-cache, private
Content-Length: 605
Content-Type: application/json
Date: Sat, 13 Jun 2020 12:26:49 GMT
{
"apiVersion": "wardle.example.com/v1alpha1",
"kind": "Flunder",
"metadata": {
"creationTimestamp": "2020-06-13T12:26:49Z",
"labels": {
"sample-label": "true"
},
"managedFields": [
{
"apiVersion": "wardle.example.com/v1alpha1",
"fieldsType": "FieldsV1",
"fieldsV1": {
"f:metadata": {
"f:labels": {
".": {},
"f:sample-label": {}
}
}
},
"manager": "HTTPie",
"operation": "Update",
"time": "2020-06-13T12:26:49Z"
}
],
"name": "my-first-flunder",
"namespace": "default",
"resourceVersion": "3",
"selfLink": "/apis/wardle.example.com/v1alpha1/namespaces/default/flunders/my-first-flunder",
"uid": "2d323301-1447-4cd4-967d-bd07eac3a49f"
},
"spec": {},
"status": {}
}
my-first-flunder
Objectが作成できました。
あらためてGETすると、上記で作成したmy-first-flunder
が返ってきます。
$ http --verify=no --cert client.crt --cert-key client.key \
https://localhost:8443/apis/wardle.example.com/v1alpha1/namespaces/default/flunders
HTTP/1.1 200 OK
Cache-Control: no-cache, private
Content-Length: 731
Content-Type: application/json
Date: Sat, 13 Jun 2020 12:29:30 GMT
{
"apiVersion": "wardle.example.com/v1alpha1",
"items": [
{
"metadata": {
"creationTimestamp": "2020-06-13T12:26:49Z",
"labels": {
"sample-label": "true"
},
"managedFields": [
{
"apiVersion": "wardle.example.com/v1alpha1",
"fieldsType": "FieldsV1",
"fieldsV1": {
"f:metadata": {
"f:labels": {
".": {},
"f:sample-label": {}
}
}
},
"manager": "HTTPie",
"operation": "Update",
"time": "2020-06-13T12:26:49Z"
}
],
"name": "my-first-flunder",
"namespace": "default",
"resourceVersion": "3",
"selfLink": "/apis/wardle.example.com/v1alpha1/namespaces/default/flunders/my-first-flunder",
"uid": "2d323301-1447-4cd4-967d-bd07eac3a49f"
},
"spec": {},
"status": {}
}
],
$ http --verify=no --cert client.crt --cert-key client.key DELETE https://localhost:8443/apis/wardle.example.com/v1alpha1/namespaces/default/flunders/my-first-flunder
このFlunder Obejectが作られるとどうなるの!? と思ったかもしれませんが、特に何も起こりません。
Flunder Objectを作ったり、削除できたりするだけです。
あくまでサンプルということですね。
終わりに
以上がSample APIServerを動かすための動かし方・遊び方でした。
さらに詳しく知りたい方は、デバッガーを使ってどういう処理をしているのかを学ぶと良いでしょう(自分もまだやってませんが)。
kube-apiserverの処理をベースに、Aggredated APIServerが実装されているため、システムコンポーネントであるkube-apiserverに対する理解も深まるはずです。
以上