2.17水平自动扩容和缩容HPA

3.1Networkpolicy

3.2Kubernetes用户安全控制

3.3Kubernetes创建普通用户

1、kubernetes HPA(Horizontal Pod Autoscaling):根据监控指标(cpu 使用率、磁盘、自定义的等)自动扩容或缩容服务中的pod数量,当业务需求增加时,系统将无缝地自动增加适量 pod 容器,提高系统稳定性。

整体逻辑:K8s 的 HPA controller 已经实现了一套简单的自动扩缩容逻辑,默认情况下,每 15s 检测一次指标,只要检测到了配置 HPA 的目标值,则会计算出预期的工作负载的副本数,再进行扩缩容操作。同时,为了避免过于频繁的扩缩容,默认在 5min 内没有重新扩缩容的情况下,才会触发扩缩容。

• 缺陷:HPA 本身的算法相对比较保守,可能并不适用于很多场景。例如,一个快速的流量突发场景,如果正处在 5min 内的 HPA 稳定期,这个时候根据 HPA 的策略,会导致无法扩容。

• pod数量计算方式:通过现有 pods 的 CPU 使用率的平均值(计算方式是最近的 pod 使用量(最近一分钟的平均值,从 metrics-server 中获得)除以设定的每个 Pod 的 CPU 使用率限额)跟目标使用率进行比较,并且在扩容时,还要遵循预先设定的副本数限制:MinReplicas <= Replicas <= MaxReplicas。计算扩容后 Pod 的个数:sum(最近一分钟内某个 Pod 的 CPU 使用率的平均值)/CPU 使用上限的整数+1

1.1安装metrics-server: 官方仓库地址:https://github.com/kubernetes-sigs/metrics-server

wget https://github.com/kubernetes-sigs/metrics-server/releases/download/v0.4.0/components.yaml
在部署之前,修改 components.yaml 的镜像地址为:
hostNetwork: true  # 使用hostNetwork模式
containers:
- name: metrics-server
  image: cnych/metrics-server:v0.4.0
  
  
kubectl apply -f components.yaml
kubectl get pods -n kube-system -l k8s-app=metrics-server

水平扩容、缩容

kubectl scale deployment ng-upgrade --replicas=5

kubectl scale deployment ng-upgrade --replicas=2


2.NetworkPolicy用来控制Pod与Pod之间的网络通信,它也支持针对Namespace进行限制。基于白名单模式,符合规则的对象通过,不符合的拒绝。

应用场景举例:

  • Pod A不能访问Pod B;
  • 开发环境所有Pod不能访问测试命名空间;
  • 提供对外访问时,限制外部IP;

示例:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: test-network-policy
  namespace: default
spec:
  podSelector:
    matchLabels:
      role: db
  policyTypes:
    - Ingress
    - Egress
  ingress:
    - from:
        - ipBlock:
            cidr: 172.17.0.0/16
            except:
              - 172.17.1.0/24
        - namespaceSelector:
            matchLabels:
              project: myproject
        - podSelector:
            matchLabels:
              role: frontend
      ports:
        - protocol: TCP
          port: 6379
  egress:
    - to:
        - ipBlock:
            cidr: 10.0.0.0/24
      ports:
        - protocol: TCP
          port: 5978

说明:必需字段:apiVersion、 kind 和 metadata 字段。

podSelector:定义目标Pod的匹配标签,即哪些Pod会生效此策略;

policyTypes:表示给定的策略是应用于目标Pod的入站流量(Ingress)还是出站流量(Egress),或两者兼有。 如果NetworkPolicy未指定policyTypes则默认情况下始终设置Ingress。

ingress:定义入流量限制规则,from用来定义白名单对象,比如网段、命名空间、Pod标签,Ports定义目标端口。

egress:定义出流量限制规则,定义可以访问哪些IP和端口

案例一:

需求:aming命名空间下所有Pod可以互相访问,也可以访问其他命名空间Pod,但其他命名空间不能访问aming命名空间Pod。

创建测试Pod

kubectl run busybox --image=busybox -- sleep 3600  ## default命名空间里创建busybox Pod
kubectl run busybox --image=busybox -n aming -- sleep 3600    ## aming命名空间里创建busybox Pod
kubectl run web --image=nginx:1.23.2 -n aming  ## aming命名空间里创建web pod

kubernetes-2.3_Pod

在没有创建NetworkPolicy的情况下测试

kubectl exec busybox -n aming -- ping 10.0.1.16  ##aming命名空间的busybox ping default命名空间的busybox IP 
kubectl exec busybox -n aming -- ping 10.0.1.17 ##aming命名空间的busybox ping aming命名空间的web IP
kubectl exec busybox -- ping 10.0.1.17 ##default命名空间的busybox ping aming命名空间的web IP

kubernetes-2.3_Pod_02

创建networkpolicy的YAML

vi  deny-all-namespaces.yaml

[root@master01 test]# cat deny-all-namespaces.yaml 
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: deny-all-namespaces
  namespace: aming
spec:
  podSelector: {} # 为空,表示匹配本命名空间所有Pod
  policyTypes:
  - Ingress
  ingress:
    - from:
      - podSelector: {} # 为空,表示匹配该命名空间所有Pod,即允许该命名空间所有Pod访问,没有定义namespaceSelector,也就是说不允许其它namespace的Pod访问。
[root@master01 test]# kubectl  apply -f deny-all-namespaces.yaml 
networkpolicy.networking.k8s.io/deny-all-namespaces created
[root@master01 test]# 

再次测试:

kubectl exec busybox -n aming -- ping 10.0.1.16  ##aming命名空间的busybox ping default命名空间的busybox IP 
kubectl exec busybox -n aming -- ping 10.0.1.17 ##aming命名空间的busybox ping aming命名空间的web IP
kubectl exec busybox -- ping 10.0.1.17 ##default命名空间的busybox ping aming命名空间的web IP

k8s用户安全控制

1)安全控制三阶段

三阶段: 认证(Authentication)、授权(Authorization)、准入控制(Admission Control)

kubernetes-2.3_Pod_03

① 所谓认证,就是先验证用户的身份是否合法,比如看看其证书是否合法有效,看看其Token是否正确;

② 所谓授权,就是看看这个用户是否有权限来访问或者操作K8s的资源;

③ 所谓准入控制,就是检查对应客户端的请求是否符合对应请求或操作API规范,检查传递参数是否是正确的。比如创建Pod,它会检查提交的信息是否符合创建Pod的规范,如果不符合规范就拒绝。

另外,准入控制还会帮助我们把我们没有明确指定的字段信息,通过默认值的方式把对应的字段填充到客户端请求中, 然后把填充好的信息一并由APIserver把客户端请求更新到对应资源在etcd中的对应信息上。

两种认证方式

① Kubeconfig 这种是基于https ca证书认证,咱们命令行管理K8s用的就是这种认证

② Token 这种通过一个Token来识别用户,比如前面我们讲dashboard时,有创建一个serviceaccount,然后再获取其token

3)K8s授权(Authorization)

授权模式:

  • AlwaysDeny:表示拒绝所有的请求,一般用于测试
  • AlwaysAllow:允许接收所有请求,如果集群不需要授权流程,则可以采用该策略
  • ABAC(Attribute-Based Access Control):基于属性的访问控制,表示使用用户配置的授权规则对用户请求进行匹配和控制(老版本采用的方式,也就是定义属性的访问类型,如果用户拥有这个属性就能访问对应的资源。需要定义一长串的属性,并且ABAC修改完之后并不能生效,现在淘汰了)
  • Webbook:通过调用外部 REST 服务对用户进行授权(在集群外部对集群鉴权)
  • RBAC(Role-Based Access Control):基于角色的访问控制,现行的默认规则(拥有角色就代表拥有访问资源某些权限)

查看你的K8s授权模式:

[root@master01 test]# cat /etc/kubernetes/manifests/kube-apiserver.yaml |grep authorization-mode
    - --authorization-mode=Node,RBAC
[root@master01 test]# 

RBAC 授权模式:

RBAC资源对象:Subject(包括:User, Group, ServiceAccount)Role(角色)、ClusterRole(集群角色)、RoleBinding(角色绑定)、ClusterRoleBinding(集群角色绑定)

主体(subject)

    • User:用户

    • Group:用户组

    • ServiceAccount:服务账号

角色

    • Role:授权特定命名空间的访问权限

    • ClusterRole:授权所有命名空间的访问权限

角色绑定

    • RoleBinding:将角色绑定到主体(即subject)

  • ClusterRoleBinding:将集群角色绑定到主体

kubernetes-2.3_IP_04

4)K8s准入控制(Adminssion Control)

Adminssion Control实际上是一个准入控制器插件列表,发送到API Server的请求都需要经过这个列表中的每个准入控制器插件的检查,检查不通过,则拒绝请求。

查看可以启用的准入控制器列表:

[root@master01 test]# kubectl exec kube-apiserver-master01 -n kube-system -- kube-apiserver -h | grep '    --enable-admission-plugins'     
      --enable-admission-plugins strings       admission plugins that should be enabled in addition to default enabled ones (NamespaceLifecycle, LimitRanger, ServiceAccount, TaintNodesByCondition, PodSecurity, Priority, DefaultTolerationSeconds, DefaultStorageClass, StorageObjectInUseProtection, PersistentVolumeClaimResize, RuntimeClass, CertificateApproval, CertificateSigning, ClusterTrustBundleAttest, CertificateSubjectRestriction, DefaultIngressClass, MutatingAdmissionWebhook, ValidatingAdmissionPolicy, ValidatingAdmissionWebhook, ResourceQuota). Comma-delimited list of admission plugins: AlwaysAdmit, AlwaysDeny, AlwaysPullImages, CertificateApproval, CertificateSigning, CertificateSubjectRestriction, ClusterTrustBundleAttest, DefaultIngressClass, DefaultStorageClass, DefaultTolerationSeconds, DenyServiceExternalIPs, EventRateLimit, ExtendedResourceToleration, ImagePolicyWebhook, LimitPodHardAntiAffinityTopology, LimitRanger, MutatingAdmissionWebhook, NamespaceAutoProvision, NamespaceExists, NamespaceLifecycle, NodeRestriction, OwnerReferencesPermissionEnforcement, PersistentVolumeClaimResize, PersistentVolumeLabel, PodNodeSelector, PodSecurity, PodTolerationRestriction, Priority, ResourceQuota, RuntimeClass, ServiceAccount, StorageObjectInUseProtection, TaintNodesByCondition, ValidatingAdmissionPolicy, ValidatingAdmissionWebhook. The order of plugins in this flag does not matter.
[root@master01 test]# 

查看当前K8s启用的准入控制器:

[root@master01 test]# grep 'admission' /etc/kubernetes/manifests/kube-apiserver.yaml
    - --enable-admission-plugins=NodeRestriction
[root@master01 test]# 

启用准入控制器:

kubectl exec kube-apiserver-master01 -n kube-system -- kube-apiserver --enable-admission-plugins=NamespaceLifecycle,LimitRanger,... 

关闭准入控制器:

kubectl exec kube-apiserver-master01 -n kube-system -- kube-apiserver --disable-admission-plugins=PodNodeSelector,AlwaysDeny,... 

5)RBAC示例

需求1:创建一个Role和ServiceAccount并把他们绑定起来。ServiceAccount有get、list、watch的权限

[root@master01 test]# cat  > testsa.yaml <<EOF
> apiVersion: v1
> kind: ServiceAccount
> metadata:
>   name: testsa
> 
> ---
> apiVersion: rbac.authorization.k8s.io/v1
> kind: Role
> metadata:
>   name: testsa-role
> rules:
> - apiGroups:  # api组,例如apps组,空值表示是核心API组,像namespace、pod、service、pv、pvc都在里面
>   - ""
>   resources: #资源名称(复数),例如pods, deployments, services
>   - pods
>   verbs: # 允许的操作,这里允许get, list, watch
>   - get
>   - list
>   - watch
> 
> ---
> apiVersion: rbac.authorization.k8s.io/v1
> kind: RoleBinding
> metadata:
>   name: testsa-rolebinding
> roleRef:
>   apiGroup: rbac.authorization.k8s.io
>   kind: Role
>   name: testsa-role
> subjects:
> - kind: ServiceAccount
>   name: testsa
> EOF
[root@master01 test]# 
[root@master01 test]# ll
total 8
-rw-r--r-- 1 root root 432 Jul 30 23:08 deny-all-namespaces.yaml
-rw-r--r-- 1 root root 683 Jul 30 23:41 testsa.yaml
[root@master01 test]# kubectl apply -f testsa.yaml
serviceaccount/testsa created
role.rbac.authorization.k8s.io/testsa-role created
rolebinding.rbac.authorization.k8s.io/testsa-rolebinding created

生成token:
[root@master01 test]# kubectl create token testsa
eyJhbGciOiJSUzI1NiIsImtpZCI6IlhmZUEtVXl3UVhtNEt6dGlXdm9rUWxBSHlNS0t2ZDVWOHVqcHNCTGNqS2cifQ.eyJhdWQiOlsiaHR0cHM6Ly9rdWJlcm5ldGVzLmRlZmF1bHQuc3ZjLmNsdXN0ZXIubG9jYWwiXSwiZXhwIjoxNzIyMzU3ODAyLCJpYXQiOjE3MjIzNTQyMDIsImlzcyI6Imh0dHBzOi8va3ViZXJuZXRlcy5kZWZhdWx0LnN2Yy5jbHVzdGVyLmxvY2FsIiwianRpIjoiZWVmOGNlZjctNzZjYS00ODlkLWE2NzctYjkxYjdkYzQyNThlIiwia3ViZXJuZXRlcy5pbyI6eyJuYW1lc3BhY2UiOiJkZWZhdWx0Iiwic2VydmljZWFjY291bnQiOnsibmFtZSI6InRlc3RzYSIsInVpZCI6IjM0NjE2YThhLTlmYjItNDdmOC1hNmUzLTZlYjkyYWEzMjQzNyJ9fSwibmJmIjoxNzIyMzU0MjAyLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6ZGVmYXVsdDp0ZXN0c2EifQ.P-xAF2VEjLyo4ogWMke32MRo5FdY5skvphPam_ACG_k6NuwypxXnouKuwGqDYmc5ONNxG4mcyvQ_PqogqDW7yc7iVd1IjBlr8-BcVfkNXax_rwXx4Jk0VqZn-5TYvxBArNT5pREdYGQA27y9mqumnskIZmdnUyBkMy1ycEiYnvF0TfldqGFg1WfTMyXjRx_8c-okj_oTL-m9eUykY2uBkJItXgB2hYCbHUkfkCHFp29VDQxKc3Su-3Y8Xj2cEHSh6ud4uzn0ZTc_HryHH4-ocCxNmF_k3kfm2zBGgHXY7EGd-Pl6SlmDqFzELlDbLZzksJiHKh1Zie-hLjVg77Wgcg
[root@master01 test]#

需求2:

给user1用户授权aming命名空间Pod读取权限

① 生成ca证书

[root@master01 test]# cd /etc/kubernetes/pki/
[root@master01 pki]# openssl genrsa -out user1.key 2048
[root@master01 pki]# openssl req -new -key user1.key -out user1.csr -subj "/CN=user1"
[root@master01 pki]# openssl x509 -req -in user1.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out user1.crt -days 3650
Certificate request self-signature ok
subject=CN = user1
[root@master01 pki]#

kubernetes-2.3_命名空间_05

② 生成kubeconfig授权文件

# 设置集群
kubectl config set-cluster myk8s \
--certificate-authority=/etc/kubernetes/pki/ca.crt \
--embed-certs=true \
--server=https://192.168.222.31:6443 \
--kubeconfig=/root/user1.kubecfg

# 查看user1配置,users和context都为空
kubectl config view --kubeconfig=/root/user1.kubecfg

# 设置客户端认证
kubectl config set-credentials user1 \
--client-key=user1.key \
--client-certificate=user1.crt \
--embed-certs=true \
--kubeconfig=/root/user1.kubecfg


# 查看user1配置,users有内容了
kubectl config view --kubeconfig=/root/user1.kubecfg

# 设置context
kubectl config set-context user1@myk8s \
--cluster=myk8s \
--user=user1 \
--kubeconfig=/root/user1.kubecfg

# 查看user1配置,context已经有内容了
kubectl config view --kubeconfig=/root/user1.kubecfg

# 切换context
kubectl config use-context user1@myk8s --kubeconfig=/root/user1.kubecfg


kubernetes-2.3_Pod_06

kubernetes-2.3_命名空间_07

③ 创建角色

[root@master01 test]# cat > user1-role.yaml <<EOF
> apiVersion: rbac.authorization.k8s.io/v1
> kind: Role
> metadata:
>   namespace: aming
>   name: user1-role
> rules:
> - apiGroups:  
>   - ""
>   resources:  
>   - pods
>   verbs: 
>   - get
>   - list
>   - watch
> EOF
[root@master01 test]# kubectl apply -f user1-role.yaml
role.rbac.authorization.k8s.io/user1-role created

④ 将用户与角色绑定

cat > user1-rolebinding.yaml <<EOF
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: user1-rolebinding
  namespace: aming
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: user1-role
subjects:
- kind: User
  name: user1
  apiGroup: rbac.authorization.k8s.io
EOF

kubectl apply -f user1-rolebinding.yaml

kubernetes-2.3_Pod_08

⑤ 创建系统用户并使用user1的配置

useradd aming
mkdir /home/aming/.kube
cp /root/user1.kubecfg /home/aming/.kube/config
chown -R aming.aming /home/aming/.kube/

kubernetes-2.3_IP_09

⑥ 切换到普通用下并访问k8s

su - aming
$ kubectl get po
$ kubectl get po -n aming
$ kubectl get deploy -n aming

kubernetes-2.3_命名空间_10