GKEのkube-apiserverにcurlしたり、opensslしたりする
GKEの設定
VPCネイティブで、マスターノードがグローバルIPを持つGKEクラスタを作成する。
❯ gcloud container clusters list
NAME LOCATION MASTER_VERSION MASTER_IP MACHINE_TYPE NODE_VERSION NUM_NODES STATUS
cluster-1 us-central1-c 1.22.8-gke.201 <master-ip> g1-small 1.21.11-gke.1100 * 1 RUNNING
Node Versionはちょっと古い。 MASTER_IP
が、マスターノードのIPアドレス。このアドレスが、kubectl get
などのAPIリクエストを受け付ける。
kubecofig
のclusterを確認すると、
❯ kubectl config view --minify -o json | jq '.clusters[].cluster.server'
"https://<master-ip>"
となっていて、kube-apiserverを指定している。
kube-apiserverにcurlしてみる
https://<master-ip>
はどこからでもアクセスできる。 curl
してみると、
❯ curl https://<master-ip>/version --insecure
{
"major": "1",
"minor": "22",
"gitVersion": "v1.22.8-gke.201",
"gitCommit": "2dca91e5224568a093c27d3589aa0a96fd3ddc9a",
"gitTreeState": "clean",
"buildDate": "2022-05-11T18:39:02Z",
"goVersion": "go1.16.14b7",
"compiler": "gc",
"platform": "linux/amd64"
}%
試しにPodを作って、curlでその情報を取得してみる。
❯ kubectl run test-nginx --image=nginx
❯ kubectl get pods
NAME READY STATUS RESTARTS AGE
test-nginx 1/1 Running 0 148m
curlでリクエストを送るときに、Authorization
ヘッダーにBearer Tokenを付加する。 Tokenは自分が使っている認証情報を使ってみる。GKEの場合、kubectlのauth pluginがバイナリgke-gcloud-auth-plugin
で提供されるようになっていて、これを使えば自分の使っているTokenがわかる。
詳しくは、Here's what to know about changes to kubectl authentication coming in GKE v1.25を参照。
❯ curl -H 'Authorization: Bearer <token> ' https://<master-ip>/api/v1/namespaces/default/pods --insecure
{
"kind": "PodList",
"apiVersion": "v1",
"metadata": {
"resourceVersion": "7243326"
},
"items": [
{
"metadata": {
"name": "test-nginx",
"namespace": "default",
"uid": "64e54acf-ad01-48e8-b7ea-ede75f4b3783",
"resourceVersion": "7186331",
"creationTimestamp": "2022-06-06T10:53:22Z",
"labels": {
"run": "test-nginx"
},
"managedFields": [
{
"manager": "kubectl-run",
"operation": "Update",
"apiVersion": "v1",
...
Tokenは例えば、KubernetesリソースのSecretのTokenを使うこともできる。下の例はdefaultで作成されているsecretのToken
❯ kubectl get secrets default-token-rqlnh -o json | jq '.data.token'
このService AccountにはKubernetesリソースをgetしたりlistしたりする権限がないので、 Authorization
ヘッダーに付加してもリソースは取得できない。
❯ curl -H 'Authorization: Bearer <token> ' https://<master-ip>/api/v1/namespaces/default/pods --insecure
# 権限がない
Podからkube-apiserverにcurlする
Kubernetesクラスタには default
namespaceに kubernetes
というServiceが存在している。
❯ kubectl get service kubernetes
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.3.0.1 <none> 443/TCP 13d
kubernetes
Serviceははkube-apiserverをクラスタ内部のPodなどに公開(?言い方わからない)するモノっぽい。 試しに先ほど作った test-nginx
Podからcurlしてversion情報を見てみる。
❯ kubectl exec -it test-nginx -- curl https://kubernetes/version --insecure
{
"major": "1",
"minor": "22",
"gitVersion": "v1.22.8-gke.201",
"gitCommit": "2dca91e5224568a093c27d3589aa0a96fd3ddc9a",
"gitTreeState": "clean",
"buildDate": "2022-05-11T18:39:02Z",
"goVersion": "go1.16.14b7",
"compiler": "gc",
"platform": "linux/amd64"
}
kube-apiserverの証明書を確認してみる。
curlをするときに、--insecure
オプションをつけていたが、これはkube-apiserverがオレオレCAを持っているから(だとおもう)。
opensslで、証明書を取得してみる。
❯ openssl s_client -connect <master-ip>:443 -showcerts
このコマンドでとってきた証明書を適当なファイルに読み出して、中身を見てみる。
❯ cat kube-apiserver.crt
-----BEGIN CERTIFICATE-----
.
.
.
-----END CERTIFICATE-----
❯ openssl x509 -text -noout -in kube-apiserver.crt
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
68:ea:18:0f:19:6a:b5:cf:52:83:13:e6:17:f7:28:8d
Signature Algorithm: sha256WithRSAEncryption
Issuer: CN=87168ee7-7f11-42ec05d92e
Validity
Not Before: May 23 13:46:35 2022 GMT
Not After : May 22 13:48:35 2027 GMT
Subject: CN=<master-ip>
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
...
...
X509v3 extensions:
X509v3 Key Usage: critical
Digital Signature, Key Encipherment
X509v3 Extended Key Usage:
TLS Web Server Authentication
X509v3 Basic Constraints: critical
CA:FALSE
X509v3 Authority Key Identifier:
keyid:ED:F3:CE:A1:7A:1D:3F:8F:45:09:86:4D:17:D6:B1:6E:B7:D5:34:47
X509v3 Subject Alternative Name:
DNS:kubernetes, DNS:kubernetes.default, DNS:kubernetes.default.svc, DNS:kubernetes.default.svc.cluster.local, IP Address:<master-ip> , IP Address:10.3.0.1
...
...
CNが<master-ip>になっている。SANにdefault
namespaceのkubernetes
ServiceのDNS名や、そのServiceのIPアドレスが設定されている。