k8s安全04--kube-apiserver 安全配置

2023-11-19

1 介紹

k8s安全02–云安全工具与安全运行时k8s安全03–云安全工具 kube-bench & OPA 介绍了云安全常见的工具, 本文继续上述两篇文章,介绍 k8s 中 apiserver相关的安全配置。

2 安全配置

2.1 配置 insecure-port

k8s 集群中可以通过配置api-server 启动命令的–insecure-port=0 来配置api-server 的本地端口安全。
docs/concepts/security/controlling-access

root@kmaster:/home/xg# sed -e '/insecure-port/s/^/#/g' -i /etc/kubernetes/manifests/kube-apiserver.yaml
root@kmaster:/home/xg# cat /etc/kubernetes/manifests/kube-apiserver.yaml |grep inse
#    - --insecure-port=0

root@kmaster:/home/xg# kube-bench
...
[PASS] 1.2.15 Ensure that the admission control plugin NamespaceLifecycle is set (Scored)
[FAIL] 1.2.16 Ensure that the admission control plugin PodSecurityPolicy is set (Scored)
[PASS] 1.2.17 Ensure that the admission control plugin NodeRestriction is set (Scored)
[PASS] 1.2.18 Ensure that the --insecure-bind-address argument is not set (Scored)
[FAIL] 1.2.19 Ensure that the --insecure-port argument is set to 0 (Scored)
[PASS] 1.2.20 Ensure that the --secure-port argument is not set to 0 (Scored)
...

2.2 RBAC

创建role 并通过rolebinding来绑定
Using RBAC Authorization

1. 创建 role
$ vim limitonerole.yaml 
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: prod-a
  name: limitone
rules:
- apiGroups: [""] # "" indicates the core API group
  resources: ["pods"]
  verbs: ["get", "watch", "delete"]
rolebind

$ kubectl auth reconcile -f limitonerole.yaml
$ kubectl -n prod-a get role

2. 创建RoleBinding
$ vim limitonebind.yaml 
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: manage-pods
  namespace: prod-a
subjects:
- kind: User
  name: paul
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role
  name: limitone 
  apiGroup: rbac.authorization.k8s.io

$ kubectl auth reconcile -f limitonebind.yaml
$ kubectl -n prod-a get rolebindings.rbac.authorization.k8s.io

2.3 Service Accounts

創建SA, 並設置到pod配置中
Configure Service Accounts for Pods

1. 创建 pod
$ vim simplepod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: simple-pod
  namespace: prod-b
spec:
  containers:
  - name: simple
    image: nginx
    
$ kubectl apply -f simplepod.yaml

2. 两个ns 的pod 都无法访问pod 信息
$ kubectl -n prod-b get pod simple-pod -oyaml|grep serviceaccount
    - mountPath: /var/run/secrets/kubernetes.io/serviceaccount

# root@simple-pod:/# curl https://kubernetes.default:443/api/v1 --insecure
{
  "kind": "Status",
  "apiVersion": "v1",
  "metadata": {
    
  },
  "status": "Failure",
  "message": "forbidden: User \"system:anonymous\" cannot get path \"/api/v1\"",
  "reason": "Forbidden",
  "details": {
    
  },
  "code": 403
}

# export TOKEN=$(cat /run/secrets/kubernetes.io/serviceaccount/token)
# curl -H "Authorization: Bearer $TOKEN" https://kubernetes.default:443/api/v1 --insecure
{
  "kind": "APIResourceList",
  "groupVersion": "v1",
  "resources": [
    {
      "name": "bindings",
      "singularName": "",
      "namespaced": true,
      "kind": "Binding",
      "verbs": [
        "create"
      ]
    },
......
    {
      "name": "services/status",
      "singularName": "",
      "namespaced": true,
      "kind": "Service",
      "verbs": [
        "get",
        "patch",
        "update"
      ]
    }
  ]
}

# curl -H "Authorization: Bearer $TOKEN" https://kubernetes.default:443/api/v1/namespaces/default/pods/ --insecure
{
  "kind": "Status",
  "apiVersion": "v1",
  "metadata": {
    
  },
  "status": "Failure",
  "message": "pods is forbidden: User \"system:serviceaccount:prod-b:default\" cannot list resource \"pods\" in API group \"\" in the namespace \"default\"",
  "reason": "Forbidden",
  "details": {
    "kind": "pods"
  },
  "code": 403
}

$ kubectl -n prod-b get sa default  -o yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  creationTimestamp: "2021-11-11T13:37:49Z"
  name: default
  namespace: prod-b
  resourceVersion: "488820"
  uid: 942370fb-f114-4ad5-a41c-402de7e9ea08
secrets:
- name: default-token-4w7mh

4. 一个ns配置sa,且设置pod权限,另外 一个保持不便
$ vim prodbSA.yaml 
apiVersion: v1
kind: ServiceAccount
metadata:
  name: simple-sa
  namespace: prod-b
secrets:
$ kubectl create -f prodbSA.yaml 
serviceaccount/simple-sa created

$ vim SArole.yaml 
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: prod-b
  name: sa-role
rules:
- apiGroups: [""] 
  resources: ["pods"]
  verbs: ["list"]
$ kubectl create -f SArole.yaml 
role.rbac.authorization.k8s.io/sa-role created

$ vim SArolebind.yaml 
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: sa-role-bind
  namespace: prod-b
subjects:
- kind: ServiceAccount
  name: simple-sa
  namespace: prod-b
roleRef:
  kind: Role
  name: sa-role
  apiGroup: rbac.authorization.k8s.io
$ kubectl create -f SArolebind.yaml 
rolebinding.rbac.authorization.k8s.io/sa-role-bind created  

5. 设置pod权限的可以正常访问pod 信息
再 pod 中新增上述新建的SA simple-sa
$ vim simplepod.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: simple-pod
  namespace: prod-b
spec:
  serviceAccountName: simple-sa
  containers:
  - name: simple
    image: nginx

$ kubectl delete -f simplepod.yaml
pod "simple-pod" deleted
$ kubectl create -f simplepod.yaml
pod/simple-pod created

$ kubectl -n prod-b exec -it simple-pod -- bash
# export TOKEN=$(cat /run/secrets/kubernetes.io/serviceaccount/token)
# curl -H "Authorization: Bearer $TOKEN" https://192.168.2.11:6443/api/v1/namespaces/default/pods/ --insecure
{
  "kind": "Status",
  "apiVersion": "v1",
  "metadata": {
    
  },
  "status": "Failure",
  "message": "pods is forbidden: User \"system:serviceaccount:prod-b:default\" cannot list resource \"pods\" in API group \"\" in the namespace \"default\"",
  "reason": "Forbidden",
  "details": {
    "kind": "pods"
  },
  "code": 403
}
#  curl -H "Authorization: Bearer $TOKEN" https://192.168.2.11:6443/api/v1/namespaces/prod-b/pods/ --insecure
{
  "kind": "PodList",
  "apiVersion": "v1",
  "metadata": {
    "resourceVersion": "490779"
  },
  "items": [
    {
      "metadata": {
        "name": "simple-pod",
        "namespace": "prod-b",
        "uid": "32b61feb-c3d6-48d7-9d84-ce3445d691ce",
        "resourceVersion": "490723",
......
            "ready": true,
            "restartCount": 0,
            "image": "nginx:latest",
            "imageID": "docker-pullable://nginx@sha256:dfef797ddddfc01645503cef9036369f03ae920cac82d344d58b637ee861fda1",
            "containerID": "docker://467ebc051442f7eb319a2da968f8340d019a2cdf9d794966d89320af055ef5e0",
            "started": true
          }
        ],
        "qosClass": "BestEffort"
      }
    }
  ]
}

2.4 Researching Pod Security Policies

docs/concepts/policy/pod-security-policy/
PodSecurityPolicy-对不同的用户和组分配不同的PodSecurityPolicy

限制pods使用指定的目录

Which policy would I use to limit pods using hostPath to a directory, such as /data and all subdirectories?

$ vim psp01.yaml 
apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
  name: allowed-host-paths
spec:
  fsGroup: 
    rule: RunAsAny
  seLinux: 
    rule: RunAsAny
  runAsUser:
    rule: RunAsAny
  supplementalGroups:
    rule: RunAsAny
  allowedHostPaths:
    - pathPrefix: "/home"
      readOnly: true

$ kubectl -n prod-a  apply -f psp01.yaml 
Warning: policy/v1beta1 PodSecurityPolicy is deprecated in v1.21+, unavailable in v1.25+
podsecuritypolicy.policy/allowed-host-paths created

控制pod 的网络

man-pages/man7/capabilities.7.html
2. Which policy and what YAML stanza with CAP_xx would be used if you want to allow a pod from fully controlling the node’s networking?

$ vim psp02.yaml 
apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
  name: allowed-capabilities
spec:
  allowedCapabilities: 
    - CAP_NET_ADMIN
......

配置 allowedUnsafeSysctls

If a developer requires known unsafe sysctls, such as what high-performance computing may require, what yaml would you need to put into the pod spec to allow it?

apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
  name: allowed-unsafe-sysctls
spec:
  allowedUnsafeSysctls: 
    - kernel.msg*
......

2.5 Enable Pod Security Policies

1. 新建 PodSecurityPolicy
vim nopriv.yaml
apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
  name: no-priv
spec:
  privileged: false
  runAsUser:
    rule: MustRunAsNonRoot
  seLinux:
    rule: RunAsAny
  fsGroup:
    rule: RunAsAny
  supplementalGroups:
    rule: RunAsAny
  volumes:
  - '*'

$ kubectl apply -f nopriv.yaml 
Warning: policy/v1beta1 PodSecurityPolicy is deprecated in v1.21+, unavailable in v1.25+
podsecuritypolicy.policy/no-priv created

2. 新建普通的pod,可以正常新建
$ kubectl create deployment busybox --image=busybox:1.32 -- sleep infinity

3. 配置 PodSecurityPolicy,使其生效
vim /etc/kubernetes/manifests/kube-apiserver.yaml
...
- --enable-admission-plugins=NodeRestriction,PodSecurityPolicy
...

4. 新建busybox2, 并查看报错信息,发现其受到 PodSecurityPolicy 限制
$ kubectl create deployment busybox2 --image=busybox:1.32 -- sleep infinity
$ kubectl get deploy
NAME       READY   UP-TO-DATE   AVAILABLE   AGE
busybox    1/1     1            1           13m
busybox2   0/1     0            0           11s
$ kubectl describe rs busybox2-648559c4d4
$Events:
  Type     Reason        Age                From                   Message
  ----     ------        ----               ----                   -------
  Warning  FailedCreate  8s (x14 over 49s)  replicaset-controller  Error creating: pods "busybox2-648559c4d4-" is forbidden: PodSecurityPolicy: unable to admit pod: []

5. 取消 PodSecurityPolicy 配置和 psp 策略后,可以正常新建服务
$ /etc/kubernetes/manifests/kube-apiserver.yaml 中去掉PodSecurityPolicy
- --enable-admission-plugins=NodeRestriction  
kubectl delete psp no-priv
$ kubectl create deployment busybox2 --image=busybox:1.32 -- sleep infinity
$ kubectl get pod
NAME                        READY   STATUS    RESTARTS   AGE
busybox-6b8867777d-gs4qj    1/1     Running   0          34m
busybox2-648559c4d4-7lcpb   1/1     Running   0          5s

2.6 Enabling API Server Auditing

# vim /etc/kubernetes/simple-policy.yaml
apiVersion: audit.k8s.io/v1
kind: Policy
rules:
- level: Metadata

# vim /etc/kubernetes/manifests/kube-apiserver.yaml 
apiVersion: v1
kind: Pod
metadata:
  annotations:
    kubeadm.kubernetes.io/kube-apiserver.advertise-address.endpoint: 192.168.2.11:6443
  creationTimestamp: null
  labels:
    component: kube-apiserver
    tier: control-plane
  name: kube-apiserver
  namespace: kube-system
spec:
  containers:
  - command:
    - kube-apiserver
    ...
    - --audit-log-maxage=7
    - --audit-log-maxbackup=2
    - --audit-log-maxsize=50
    - --audit-log-path=/var/log/audit.log
    - --audit-policy-file=/etc/kubernetes/simple-policy.yaml
    ...
    image: registry.aliyuncs.com/google_containers/kube-apiserver:v1.21.4
    ...
    volumeMounts:
    - mountPath: /etc/kubernetes/simple-policy.yaml
      name: audit
      readOnly: true
    - mountPath: /var/log/audit.log
      name: audit-log
      readOnly: false
    ...
  hostNetwork: true
  priorityClassName: system-node-critical
  volumes:
  - hostPath:
      path: /etc/kubernetes/simple-policy.yaml
      type: File
    name: audit
  - hostPath:
      path: /var/log/audit.log
      type: FileOrCreate
    name: audit-log
  ...
status: {}

更新后 api-server 就正常重启:

root@kmaster:/home/xg# docker ps |grep apiserver
797c8636f865   cef7457710b1                                          "kube-apiserver --ad…"   38 seconds ago   Up 38 seconds             k8s_kube-apiserver_kube-apiserver-kmaster_kube-system_0e9626cb6a8df5c71073e401abc687eb_0
14f4304feef2   registry.aliyuncs.com/google_containers/pause:3.4.1   "/pause"                 38 seconds ago   Up 38 seconds             k8s_POD_kube-apiserver-kmaster_kube-system_0e9626cb6a8df5c71073e401abc687eb_0

发现持续出现审计日志:

root@kmaster:/home/xg# tail -n 3 /var/log/audit.log
{"kind":"Event","apiVersion":"audit.k8s.io/v1","level":"Metadata","auditID":"6c71e531-c823-4c86-b0b1-0c8d20f77400","stage":"ResponseComplete","requestURI":"/apis/crd.projectcalico.org/v1/clusterinformations/default","verb":"get","user":{"username":"system:serviceaccount:kube-system:calico-kube-controllers","uid":"1346c03c-7aa9-48d1-b6eb-ca5356f9e75d","groups":["system:serviceaccounts","system:serviceaccounts:kube-system","system:authenticated"],"extra":{"authentication.kubernetes.io/pod-name":["calico-kube-controllers-58497c65d5-rlz7x"],"authentication.kubernetes.io/pod-uid":["63c1d7ca-0426-40db-9161-aa46b3ebddf3"]}},"sourceIPs":["10.224.189.2"],"userAgent":"Go-http-client/2.0","objectRef":{"resource":"clusterinformations","name":"default","apiGroup":"crd.projectcalico.org","apiVersion":"v1"},"responseStatus":{"metadata":{},"code":200},"requestReceivedTimestamp":"2021-11-09T00:02:41.779246Z","stageTimestamp":"2021-11-09T00:02:41.793716Z","annotations":{"authorization.k8s.io/decision":"allow","authorization.k8s.io/reason":"RBAC: allowed by ClusterRoleBinding \"calico-kube-controllers\" of ClusterRole \"calico-kube-controllers\" to ServiceAccount \"calico-kube-controllers/kube-system\""}}
{"kind":"Event","apiVersion":"audit.k8s.io/v1","level":"Metadata","auditID":"f080f4c4-49cf-458b-902b-05409fbf6206","stage":"RequestReceived","requestURI":"/healthz?timeout=32s","verb":"get","user":{"username":"system:serviceaccount:kube-system:calico-kube-controllers","uid":"1346c03c-7aa9-48d1-b6eb-ca5356f9e75d","groups":["system:serviceaccounts","system:serviceaccounts:kube-system","system:authenticated"],"extra":{"authentication.kubernetes.io/pod-name":["calico-kube-controllers-58497c65d5-rlz7x"],"authentication.kubernetes.io/pod-uid":["63c1d7ca-0426-40db-9161-aa46b3ebddf3"]}},"sourceIPs":["10.224.189.2"],"userAgent":"kube-controllers/v0.0.0 (linux/amd64) kubernetes/$Format","requestReceivedTimestamp":"2021-11-09T00:02:41.794590Z","stageTimestamp":"2021-11-09T00:02:41.794590Z"}
{"kind":"Event","apiVersion":"audit.k8s.io/v1","level":"Metadata","auditID":"f080f4c4-49cf-458b-902b-05409fbf6206","stage":"ResponseComplete","requestURI":"/healthz?timeout=32s","verb":"get","user":{"username":"system:serviceaccount:kube-system:calico-kube-controllers","uid":"1346c03c-7aa9-48d1-b6eb-ca5356f9e75d","groups":["system:serviceaccounts","system:serviceaccounts:kube-system","system:authenticated"],"extra":{"authentication.kubernetes.io/pod-name":["calico-kube-controllers-58497c65d5-rlz7x"],"authentication.kubernetes.io/pod-uid":["63c1d7ca-0426-40db-9161-aa46b3ebddf3"]}},"sourceIPs":["10.224.189.2"],"userAgent":"kube-controllers/v0.0.0 (linux/amd64) kubernetes/$Format","responseStatus":{"metadata":{},"code":200},"requestReceivedTimestamp":"2021-11-09T00:02:41.794590Z","stageTimestamp":"2021-11-09T00:02:41.795889Z","annotations":{"authorization.k8s.io/decision":"allow","authorization.k8s.io/reason":"RBAC: allowed by ClusterRoleBinding \"system:discovery\" of ClusterRole \"system:discovery\" to Group \"system:authenticated\""}}

ls 可以发现会快速产生大量日志,因此实际中需要做rotate,此处暂时直接关闭

查看审计日志量:
root@kmaster:/home/xg# ls -lh /var/log/audit.log
-rw-r--r-- 1 root root 7.9M Nov  9 00:04 /var/log/audit.log

关闭审计操作:
# vim /etc/kubernetes/manifests/kube-apiserver.yaml 
#    - --audit-policy-file=/etc/kubernetes/simple-policy.yaml # 注釋掉該行

再次查看發現已經沒有生成审计日志了:
root@kmaster:/home/xg# ls -lh /var/log/audit.log
-rw-r--r-- 1 root root 7.9M Nov  9 00:04 /var/log/audit.log
root@kmaster:/home/xg# ls -lh /var/log/audit.log
-rw-r--r-- 1 root root 13M Nov  9 00:07 /var/log/audit.log
root@kmaster:/home/xg# ls -lh /var/log/audit.log
-rw-r--r-- 1 root root 13M Nov  9 00:07 /var/log/audit.log

复杂一點的审计功能:

# vim /etc/kubernetes/moderate-policy.yaml
apiVersion: audit.k8s.io/v1 
kind: Policy
omitStages:
  - "RequestReceived"
rules:
  - level: RequestResponse
    resources:
    - group: ""
      resources: ["pods"]
  - level: Metadata
    resources:
    - group: ""
      resources: ["pods/log", "pods/status"]
  - level: Metadata
    userGroups: ["system:authenticated"]
    nonResourceURLs:
    - "/api*" 
    - "/version"
  - level: Request
    resources:
    - group: "" 
      resources: ["configmaps"]
    namespaces: ["kube-system"]
  - level: Metadata
    resources:
    - group: "" 
      resources: ["secrets", "configmaps"]
    omitStages:
      - "RequestReceived"
# vim /etc/kubernetes/manifests/kube-apiserver.yaml 
...
  volumes:
  - hostPath:
      path: /etc/kubernetes/moderate-policy.yaml # simple-policy.yaml
      type: File
    name: audit

2.7 Encrypting Secrets

1. 創建 secret
$ kubectl create secret generic first -n default  --from-literal=firstkey=first
secret/first created

2. 查看 secret
$ kubectl get secrets first -oyaml
apiVersion: v1
data:
  firstkey: Zmlyc3Q=
kind: Secret
metadata:
  creationTimestamp: "2021-11-09T23:50:29Z"
...

3. 使用base64 檢查加密的值
$ echo "Zmlyc3Q="| base64 --decode 
first

4. 在etcd 中查看secret
4.1 獲取 etcd 相關的配置
# grep etcd /etc/kubernetes/manifests/kube-apiserver.yaml
    - --etcd-cafile=/etc/kubernetes/pki/etcd/ca.crt
    - --etcd-certfile=/etc/kubernetes/pki/apiserver-etcd-client.crt
    - --etcd-keyfile=/etc/kubernetes/pki/apiserver-etcd-client.key
    - --etcd-servers=https://127.0.0.1:2379
4.2 在etcd 中查看數據信息
# docker cp 56f5b:/usr/local/bin/etcdctl /usr/bin
# ETCDCTL_API=3 etcdctl --endpoints https://192.168.2.11:2379 \
--cacert=/etc/kubernetes/pki/etcd/ca.crt \
--cert=/etc/kubernetes/pki/etcd/server.crt \
--key=/etc/kubernetes/pki/etcd/server.key \
get /registry/secrets/default/first
輸出:
k8s

v1Secret�
�
first�default"*$1245c445-cec6-4fc9-b774-24a399af74522Œ��z�c
kubectl-createUpdate�vŒ��FieldsV1:1
/{"f:data":{".":{},"f:firstkey":{}},"f:type":{}}
firstkeyfirst�Opaque�"

5. 生成随机base64字符串
$ head -c 32 /dev/urandom | base64
GRLTglCQMgwNoq0Or5OjuC2rSrt6j4P7hgDY5sGCuJY=

6. 配置yaml
vim encryptionconfig.yaml 
apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
name: newsetup
resources:
  - resources:
    - secrets
    providers:
    - aescbc:
        keys:
        - name: firstkey
          secret: GRLTglCQMgwNoq0Or5OjuC2rSrt6j4P7hgDY5sGCuJY=
    - identity: {}

7. 拷贝配置
cp encryptionconfig.yaml /etc/kubernetes/pki/

8. kube-apiserver 中追加 --encryption-provider-config 配置
vim /etc/kubernetes/manifests/kube-apiserver.yaml
...
    - --feature-gates=RemoveSelfLink=false
    - --encryption-provider-config=/etc/kubernetes/pki/encryptionconfig.yaml # add this
    image: registry.aliyuncs.com/google_containers/kube-apiserver:v1.21.4
...

9. 创建新secret
$ kubectl create secret generic second -n default --from-literal=secondkey=second
secret/second created

10. 在etcd 中查看second
# ETCDCTL_API=3 etcdctl --endpoints https://192.168.2.11:2379 \
--cacert=/etc/kubernetes/pki/etcd/ca.crt \
--cert=/etc/kubernetes/pki/etcd/server.crt \
--key=/etc/kubernetes/pki/etcd/server.key \
get /registry/secrets/default/second
/registry/secrets/default/second
k8s:enc:aescbc:v1:firstkey:cK+ˣP�
<�6'��6�m�1'E��[i�B�GGg�$(��n�+�n9�ԭ>����s�߫��j��G��z����"�=
                                                          �zē���� �AVO�6��d'"�Ш����=0X�5TU�K�
QA3�.��'7��GU�龭ցQۮ� ���>���{�Q��
                                 �	�',6FH�H�_�K��������I�-�:����Y�G�r�J�y���_;�g�qh�jTS44R<���w ��

11. 重新新建所有的secret,並确认first也被创建且加密了
$ kubectl get secrets --all-namespaces -o json | kubectl replace -f -

12. 查看first
# ETCDCTL_API=3 etcdctl --endpoints https://192.168.2.11:2379 \
...
get /registry/secrets/default/first
/registry/secrets/default/first
k8s:enc:aescbc:v1:firstkey:r�yg��JX���ި����r�Y�w�p�������қ
                                                         �]8���X��8O�:}�o���6�,��_�����D�������x
�DG���\Ć��|�w�"[w{�Ni���?44��.�˔E�*��a�� ��9z<=9H�zC�4�����CɎ�f-�k
z;ݺ����/�A9k�ptЙ����U���V���bHܙlǍ�g �1�
                         �~�
可見first已經被加密了

3 注意事项

  1. 当前k8s 版本已经支持到1.22.xx 版本, 本文基于1.22.1 版本做实验,如果版本不匹配,那么最好更新到1.22.xx版本, 以下为笔者从1.21升级到1.22的方法
    kmaster:
    # apt-mark unhold kubeadm kubectl kubelet 
    # apt-get update && apt-get install -y kubeadm=1.22.1-00 kubelet=1.22.1-00 kubectl=1.22.1-00
    # kubeadm upgrade apply v1.22.1
    
    knode01:
    # apt-mark unhold kubeadm kubectl kubelet
    # kubeadm upgrade node
    

4 说明

docs/concepts/security
concepts/security/overview/

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

k8s安全04--kube-apiserver 安全配置 的相关文章

  • 计算 .NET Core 项目的代码指标?

    我正在研究 ASP NET Core 和 NET Core 项目 对于经典的 C 项目 Visual Studio 2015 具有计算代码指标的功能 对于 NET Core 预览版 2 工具中缺少支持 在工具更加完整之前 有人知道解决方法吗
  • Emacs 强制组织模式捕获缓冲区在新窗口中打开

    如何强制组织模式的捕获缓冲区在新窗口中打开 我试过 setq special display regexps Capture 但它不起作用 我立即看到一个新窗口 然后 org mode 进行两个垂直分割 我使用 3 个垂直分割 并将捕获缓冲
  • Sencha-touch :保存登录名/密码(保存会话,多任务)

    我有一个 Java Web 应用程序 其中移动部分是用 Sencha touch 开发的 当我启动 sencha touch 应用程序时 她询问我的登录名 密码 因为该应用程序的访问受到限制 但是我想保存用户的登录名 密码 sencha t
  • f# 运行总计序列

    好吧 这看起来应该很容易 但我就是不明白 如果我有一个数字序列 如何生成由运行总计组成的新序列 例如 对于序列 1 2 3 4 我想将其映射到 1 3 6 10 以适当的功能方式 Use List scan https msdn micro
  • 结构化 scala 案例类的自定义 json 序列化

    我有一些用于往返 scala 案例类的工作 jackson scala 模块代码 Jackson 对于平面案例类非常有用 但是当我制作一个包含其他案例类列表的案例时 我似乎需要很多代码 考虑 abstract class Message c
  • iOS UITest:如何找到UITableViewCell的AccessoryView?

    你好我正在学习UITests now 我有个问题 如何检测accessoryView的点击tableViewCell 在UI测试中 下面是我的tableViewCell 我想要检测细节闭合配件视图水龙头 像这样 app tables cel
  • 增加浏览器缩放时 mediaelement.js 音量控制混乱

    媒体元素2 12 0 这种情况仅发生在 FF 和 Chrome 中 而不会发生在 IE 或 Opera 中 导航到具有媒体元素播放器的网站内容后 甚至导航到媒体元素首页http mediaelementjs com http mediael
  • 我可以在方法体内使用注释吗?

    允许 Java 注释的语义将它们放置在某处在函数体内 例如注释特定的函数调用 语句或表达式 例如 class MyClass void theFunc Thing thing String s null Catching NullPoint
  • Mink 不适用于 behat 3.0.12

    我安装了 Behat Mink 和其他一些相关的软件包 这是我的composer json 文件 require behat behat 3 0 6 behat symfony2 extension dev master behat min
  • 如何包装实体框架以在执行前拦截 LINQ 表达式?

    我想在执行之前重写 LINQ 表达式的某些部分 我在将重写器注入正确的位置时遇到问题 实际上根本没有 查看实体框架源代码 在反射器中 它最终归结为IQueryProvider Execute在 EF 中 它通过以下方式耦合到表达式Objec
  • 如何绕过警告意外的任何。指定不同的类型 @typescript-eslint/no-explicit-any

    我们有严格的零棉绒问题政策 这意味着所有错误和警告都需要修复 在我们的 React typescript 项目中面临这个 lint 错误 warning Unexpected any Specify a different type typ
  • 案例类和案例对象之间的区别?

    我正在学习 Scala 和 Akka 并且在最近的查找中solution https stackoverflow com questions 22770927 waiting for multiple results in akka 我发现
  • Bootstrap 轮播中的 Href

    我一直在Interwebz上搜索 但似乎找不到答案 如何在轮播链接中添加 href 我尝试将 a 标签放在 h1 标签之外 但它破坏了滑块本身的功能 这是我的代码 div class col sm 12 div class carousel
  • 将背景图像放入菱形容器中会导致容器失去形状

    标题总结得很好 我可以很容易地绘制菱形 但是当我将图像添加到背景时 它会为形状添加更多边 我似乎无法弄清楚为什么添加背景图像时会发生这种情况 任何意见 将不胜感激 这是我的代码 请原谅内联 css 我只是这样做 直到我有一个可行的解决方案
  • 使用node.js/Express从HTTP重定向到HTTPS

    有什么方法可以更改我的 Web 应用程序以侦听 HTTPS 而不是 HTTP 我正在使用node js express 我需要它来侦听 HTTPS 因为我正在使用地理定位 而 Chrome 不再支持地理定位 除非从 HTTPS 等安全上下文
  • win32 内容已更改,但除非移动窗口,否则不会显示更新

    我的 win32 GUI 内容每秒都会更改 但除非手动移动窗口 否则不会显示更新 我尝试每秒弹出一个消息框来触发窗口刷新 它成功了 因此 这证明我的内容确实发生了变化 但窗口没有更新 我希望刷新窗口而不是每次都弹出消息框 有没有这样的窗口功
  • vcproj/vsprops 的可选环境变量

    有没有办法在项目文件 有或没有 vsprops 中进行环境变量替换 如果找不到该变量 则用默认值替换 我还没有找到任何方法来做到这一点 因为一切似乎都会覆盖环境变量 编辑 我需要它为属性工作 而不是为环境变量工作 具体来说 可以使用指定目标
  • Carrierwave 在文件上传时抛出“堆栈级别太深”错误

    我有一个奇怪的问题 不知道如何进一步调试 如果我用 html 表单上传文件 我会得到 SystemStackError stack level too deep 痕迹是 Started POST global accounts 82 for
  • Python正则表达式:如何用不同的值替换出现的每个实例?

    假设我有这个字符串 s blah blah blah 使用Python正则表达式 如何用不同的值替换 blah 的每个实例 例如 我有一个值列表v 1 2 3 你可以使用re sub打回来 http docs python org libr
  • 神秘的 getClobVal()

    我有一个表 AKADMIN 其中包含 XMLTYPE 列 其名称为 XML 我想在该列中使用 getClobVal select t xml getClobVal t xml getClobVal t xml getClobVal as c

随机推荐

  • 2021-03-30 maven

    1 maven父子工程 3 maven环境优化 1 修改web xml为最新的 2 将maven结构搭建完整 4 编写一个servlet Javaweb下载文件的头
  • Java日志简介及SpringBoot日志

    一 什么是日志 日志 就是介绍一个过程和经历的详细记录 项目日志 就是项目开发过程的详细记录 一般由项目经理记录 代码里的日志 就是程序员记录某个开发过程的详细情况 这是项目里每个程序员需要做的工作 日志和异常处理结合得当的话 会给项目维护
  • vue+element-ui 实现弹窗验证用户信息

  • C++零散易错点总结

    对日常做题中遇到的一些零散的易错点的总结 持续更新ing 1 string的length方法返回的是无符号数 当与负数比较时需要强制类型转换 否则会报错 1
  • appium+python自动化测试

    获取APP的包名 1 aapt即Android Asset Packaging Tool 在SDK的build tools目录下 该工具可以查看apk包名和launcherActivity 2 在android sdk里面双击SDK man
  • MYSQL8隐藏索引

    问题场景 我们知道 索引太多会导致UPDATE DELETE INSERT的时候 引擎需要更新索引信息 产生额外的开销 从而影响数据库性能 所以需要清理无效索引 但是表是数年前建的 索引基本都不是自己添加的 无法准确判定是否可以删除 万一删
  • shell 脚本命令太长,如何换行?

    再加ENTER
  • ElasticSearch ES 安装 常见错误 Kibana安装 设置 权限 密码

    最近在学习ES数据库 所以将一些东西记录一下 以下所有的都是基于es7 8 0版本进行的 下载安装ES数据库 安装本体 下载地址 linux mac os windows es的安装非常简单 基本都是解压然后运行就行了 这里我们就以linu
  • 如何在十天内掌握线性代数

    最近 我的朋友斯考特 杨 Scott Young 成就了一个惊人的壮举 他在一年之内 完成了传说中的MIT计算机科学课程表的全部33门课 从线性代数到计算理论 最重要的是 他是自学的 观看在线教程讲座 并用实际的考试作自我评估 到斯考特的F
  • 时序预测

    时序预测 MATLAB实现RF 随机森林 时间序列预测 目录 时序预测 MATLAB实现RF 随机森林 时间序列预测 预测效果 基本介绍 预测准备 程序设计 主程序 训练子函数 预测子函数 参考资料 致谢 预测效果 基本介绍 在机器学习中
  • Maven依赖冲突

    依赖冲突 依赖冲突是指项目依赖的某一个jar包 有多个不同的版本 因而造成类包版本冲突 依赖传递 项目依赖了A A依赖了B 项目自动依赖了B 注意 父项目中的依赖有
  • GitHub 上最火的开源项目 —— Java 篇

    很多开发者在看到自己感兴趣的项目时会使用 Star 功能 可以说 Star 的数量在一定程度上代表了开源项目的热门程度 本文整理了 Java 语言中 star 数最多的十五款开源项目 这些项目在 GitHub 上的 star 数均超过 15
  • 开发 Leader 们最该了解的软件度量指标

    无论何时 只要是要评估或对比某些东西 就需要使用度量指标 它们是可量化的衡量标准 用于判断每个行业的进展 这其中包括软件开发 在该领域 开发负责人依靠软件度量指标来跟踪性能和生产 在我们关于如何衡量和提高开发人员工作效率的博客文章中 我们讨
  • ext 6.0开发实例二

    由于Ext JS 6将原来的Ext JS和Sencha Touch合并为一个框架 因而在使用CMD来创建应用程序前 需要考虑清楚你是要创建一个通用应用程序 还是仅仅只是针对桌面或移动设备的应用程序 要做这样的考量 是因为通用应用程序和比较单
  • 关于java/android 数据序列化后SerialVersionUID的获取

    本人android 开发 遇到了一个关于数据序列化的坑 纪录下来以便以后查看 所有需要序列化本地的bean都需要继承Serializable 否则无法序列化 如果不了解序列化的知识请自行百度 我继承了Serializable 但是没有设置S
  • 2.5.14 动态内存共享AMS

    最后更新2021 08 02 这个还算是比较实用的功能 最早介绍过CPU共享 也提到过内存共享 但CPU共享是动态 实时 按需分配的 虽然有限制条件 而内存需要用DLPar功能 收工调节 至少不是实时分配 那内存可不可以实现类似CPU的实时
  • python笔记2--python 中安装package注意事项

    python笔记2 python 中安装package注意事项 使用python时候 经常需要安装相关的包 安装方法包括两种 1 直接使用easy install或者pip安装 2 下载package源码安装 1 直接使用easy inst
  • macbook上的vim怎么设置语法高亮和显示行号

    在我写这篇文章之前我的vim就很普通 没有语法高亮 无法显示行号 但是我通过在网上不断查阅一些处理方法和经验之后 我终于能将我MacBook电脑上的vim配置出语法高亮和显示行号了 作为一名乐于分享 乐于助人的新手程序员 我决定把我的解决办
  • 《Web应用安全权威指南》学习笔记

    第1章 什么是Web应用的安全隐患 第2章 搭建试验环境 邮件发送服务器Postfix POP3服务器Dovecot SSH服务器OpenSSH Web应用调试工具Fiddler 第3章 Web安全基础 HTTP回话管理 同源策略 Cook
  • k8s安全04--kube-apiserver 安全配置

    k8s安全04 kube apiserver 安全配置 1 介紹 2 安全配置 2 1 配置 insecure port 2 2 RBAC 2 3 Service Accounts 2 4 Researching Pod Security