Skip to content

Instantly share code, notes, and snippets.

@aruruka
Last active July 30, 2021 01:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save aruruka/4ebb692f292d8543ddea76046c65b298 to your computer and use it in GitHub Desktop.
Save aruruka/4ebb692f292d8543ddea76046c65b298 to your computer and use it in GitHub Desktop.
Troubleshooting bash code snippet for Kubernetes cluster administration.

kubeadm相关

主机有双网卡,默认网卡为外网网卡,集群内通信使用内网网卡

尝试从 apiServer 参数--advertise-address和 kubelet 参数--node-ip入手。

一个出错的典型场景:

比如在物理机上通过 vagrant 创建虚拟机部署 k8s 集群,虚拟机默认可能会配置一张 NAT 网卡作为默认网卡且这个 ip 可能是一样的,那可能多个虚拟机的的默认网卡的 ip 都是一样的。

kube-dns 相关

kube-dns 的 service ip 更改导致集群内服务发现功能不可用

kube-dns 是 k8s 的一个集群内 dns 插件,解决集群内服务发现的问题。在没有任何 dns 解决方案的情况下,pod 也可以通过 service name 访问到 service,但前提是 service 创建在 pod 之前。其原因是, apiserver 在创建 pod 的时候会将现在的集群内的 service 信息注入到容器中的环境变量。

假如集群内的 pod network CIDR 是 10.96.0.0/16,那 kube-dns 默认的 service ip 将会是 10.96.0.10,这个 ip 将会成为容器的 nameserver。 假如因为 pod 网络 CIDR 发生变化,有可能 kube-dns 的 service ip 改变了,但容器中的 nameserver ip 没有及时同步。 关于集群内 DNS 的问题可以参考官网提供的经典问题分析

认证与授权相关

查看 kubectl (其它组件原理一致)的上下文(context)与用户对应的 ClusterRole/Role。

查看连接集群的上下文

  • 查看当前的 context 和 user

如下面例子,当前使用的是名为 kubernetes 的 context,用户是 kubectl

kubectl config get-contexts

CURRENT NAME CLUSTER AUTHINFO NAMESPACE backend-context kubernetes backend work

  •     kubernetes        kubernetes   kubectl    kube-system
    
  • kubectl 使用的 config 文件一般为 ~/.kube/config,也可以使用 KUBECONFIG 环境变量指定一个文件。

cluster 为 k8s 集群信息,包括 ip、端口,如果集群开启了 --insecure-port 选项,则可以通过此端口绕过认证和授权。

ls -lh ~/.kube/config

-rw------- 1 root root 6.4K Apr 17 14:21 /root/.kube/config

  • certificate-authority-data 其实是 ca 根证书经过 base64 加密后的内容,ca 证书为服务端(master)创建时生成的。

  • client-certificate 或者 client-certificate-data 则是客户端(此处为 kubectl)通过 x509 认证机制,根据 ca 证书和客户端自己的私钥(client-key)生成的。

    具体步骤可以自行 Google。

cat ~/.kube/config

Sample output:

apiVersion: v1
clusters:
- cluster:
    ...
    server: https://30.99.3.138:6443
  name: kubernetes
contexts:
- context:
    cluster: kubernetes
    namespace: work
    user: backend
  name: backend-context
- context:
    cluster: kubernetes
    namespace: kube-system
    user: kubectl
  name: kubernetes
current-context: kubernetes
kind: Config
preferences: {}
users:
- name: backend
  user:
    client-certificate: /root/work/backend.crt
    client-key: /root/work/backend.key
- name: kubectl
  user:
    client-certificate-data: ...
    client-key-data: ...

查看证书内容

  • Issuer 是 ca 证书发行方(master)设置的字段内容。

    kubernetes 系统中的用户有 2 种: 一般用户service account。 匿名用户默认名为: system:anonymous,所属组为: system:unauthenticated。

  • Subject 是客户端(kubectl)设置的内容。CN(common name) 域用作一般用户的用户名,O(organization)域用作组名。

    所以这个context中的的用户名为backend,组为dev

cat /root/work/backend.crt | openssl x509 -text -noout

Certificate: Data: Version: 1 (0x0) Serial Number: fe:0e:cd:8d:b9:07:fd:74 Signature Algorithm: sha256WithRSAEncryption Issuer: C=CN, ST=BeiJing, L=BeiJing, O=k8s, OU=System, CN=kubernetes Validity Not Before: Apr 17 05:33:19 2019 GMT Not After : Apr 16 05:33:19 2020 GMT Subject: CN=backend, O=dev Subject Public Key Info: Public Key Algorithm: rsaEncryption Public-Key: (2048 bit) Modulus: ... Exponent: 65537 (0x10001) Signature Algorithm: sha256WithRSAEncryption ...

查看RoleBiding和Role

  • RoleBinding 中的 subjects 中,有一个 user 名为 backend。

    这个 backend 就与 kubectl 的 context 中的 backend 用户相关联。 这个用户的权限就是在 backend-role 这个 Role 中配置的。 同理,subjects 中如果配置的是 group,则会和 kubectl config 文件中的 O 域相关联。

kubectl get rolebinding -n work

NAME AGE backend-rolebinding 35s

kubectl get rolebinding backend-rolebinding -o yaml -n work

Sample outpu:

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  annotations:
    kubectl.kubernetes.io/last-applied-configuration: |
      {"apiVersion":"rbac.authorization.k8s.io/v1","kind":"RoleBinding","metadata":{"annotations":{},"name":"backend-rolebinding","namespace":"work"},"roleRef":{"apiGroup":"","kind":"Role","name":"backend-role"},"subjects":[{"apiGroup":"","kind":"User","name":"backend"}]}
  creationTimestamp: 2019-04-18T06:24:27Z
  name: backend-rolebinding
  namespace: work
  resourceVersion: "7179659"
  selfLink: /apis/rbac.authorization.k8s.io/v1/namespaces/work/rolebindings/backend-rolebinding
  uid: 9e1c691e-61a2-11e9-af73-06a624003bc9
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: backend-role
subjects:
- apiGroup: rbac.authorization.k8s.io
  kind: User
  name: backend
$ kubectl get role backend-role -n work -o yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  annotations:
    kubectl.kubernetes.io/last-applied-configuration: |
      {"apiVersion":"rbac.authorization.k8s.io/v1","kind":"Role","metadata":{"annotations":{},"name":"backend-role","namespace":"work"},"rules":[{"apiGroups":[""],"resources":["pods"],"verbs":["get","list","watch"]}]}
  creationTimestamp: 2019-04-18T06:18:06Z
  name: backend-role
  namespace: work
  resourceVersion: "7178286"
  selfLink: /apis/rbac.authorization.k8s.io/v1/namespaces/work/roles/backend-role
  uid: baafff88-61a1-11e9-bc36-063270003bc8
rules:
- apiGroups:
  - ""
  resources:
  - pods
  verbs:
  - get
  - list
  - watch

验证 kubectl 的权限

  • 可以看到使用 context 为backend-context的时候,确实只有对 work namespace 下的 pod 资源的查看权限。
kubectl config use-context backend-context

Switched to context "backend-context".

kubectl config current-context

backend-context

kubectl get no

No resources found. Error from server (Forbidden): nodes is forbidden: User "backend" cannot list nodes at the cluster scope

kubectl get service -n work

No resources found. Error from server (Forbidden): services is forbidden: User "backend" cannot list services in the namespace "work"

kubectl get po -n work

No resources found.

使用 jsonpath 来遍历 clusterrolebinding 和 rolebinding,看是否有指定的 user、group 被关联

kubectl get rolebinding -n work -o jsonpath='{range .items[*]}RolebindingName: {.metadata.name}{"\t"}SubjectNames: {.subjects[*].name}{"\n"}{end}'

实用小技巧

kubectl proxy

kubectl proxy can forward the rest API of kube-apiserver to the local localhost. So you can use curl to access localhost in the OS, thus directly accessing the API of kube-apiserver.

echo -e "\n\n\n\e[92mStarting Proxy. After starting it will not output a response. Please click the first Terminal Tab\n"; kubectl proxy
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment