kubernetes notes


安装Helm、nginx-ingress

Helm

地址:https://github.com/helm/helm/releases/tag/v3.4.0

nginx-ingress
一 、安装报错
1、helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
2、一定要先随便装下
     helm install my-nginx ingress-nginx/ingress-nginx 

   然后肯定会报错,然后 两条命令
  1、kubectl logs  pod名称
  2、kubectl describe pod 你的pod名称  (这里会看到具体的错误)

  像我这里 就是 k8s.gcr.io/ingress-nginx/controller:v0.41.2  这个镜像无法下载


Events:
  Type     Reason     Age                    From               Message
  ----     ------     ----                   ----               -------
  Normal   Scheduled                default-scheduler  Successfully assigned default/my-nginx-ingress-nginx-controller-6f59b94645-28qn4 to node2
  Normal   Pulling    2m39s (x4 over 4m50s)  kubelet, node2     Pulling image "k8s.gcr.io/ingress-nginx/controller:v0.41.2@sha256:1f4f402b9c14f3ae92b11ada1dfe9893a88f0faeb0b2f4b903e2c67a0c3bf0de"
  Warning  Failed     2m24s (x4 over 4m35s)  kubelet, node2     Failed to pull image "k8s.gcr.io/ingress-nginx/controller:v0.41.2@sha256:1f4f402b9c14f3ae92b11ada1dfe9893a88f0faeb0b2f4b903e2c67a0c3bf0de": rpc error: code = Unknown desc = Error response from daemon: Get https://k8s.gcr.io/v2/: net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)
  Warning  Failed     2m24s (x4 over 4m35s)  kubelet, node2     Error: ErrImagePull
  Normal   BackOff    118s (x6 over 4m34s)   kubelet, node2     Back-off pulling image "k8s.gcr.io/ingress-nginx/controller:v0.41.2@sha256:1f4f402b9c14f3ae92b11ada1dfe9893a88f0faeb0b2f4b903e2c67a0c3bf0de"
  Warning  Failed     103s (x7 over 4m34s)   kubelet, node2     Error: ImagePullBackOff
[cyylog@master src]$  helm delete my-nginx 
二 、 解决方法
于是执行:
  docker pull giantswarm/ingress-nginx-controller:v0.41.2
然后改tag
 docker tag giantswarm/ingress-nginx-controller:v0.41.2   k8s.gcr.io/ingress-nginx/controller:v0.41.2
删之前的tag 
  docker rmi giantswarm/ingress-nginx-controller:v0.41.2

注意:各个节点都要执行
然后删掉刚才的安装  helm delete my-nginx ,然后再继续其他内容



Digest: sha256:8aa4fda472ec83ae59fe0ce9720684d769ed277ff9bdcbb0169178dc9d1f8e85
Status: Downloaded newer image for giantswarm/ingress-nginx-controller:v0.41.2
docker.io/giantswarm/ingress-nginx-controller:v0.41.2
[cyylog@master src]$ 

三 、再次安装
清除污点,允许 master 调度
kubectl taint nodes --all node-role.kubernetes.io/master- 

下载chart到本地
helm fetch ingress-nginx/ingress-nginx
修改部分内容后再次安装

helm install my-nginx ingress-nginx    -n my-nginx-ingress

更新用的是如下命令(下面用到)
helm upgrade my-nginx ingress-nginx    -n my-nginx-ingress

PS: 修改配置values.yaml

$ diff 111111.yaml values.yaml
8c8
<     digest: sha256:1f4f402b9c14f3ae92b11ada1dfe9893a88f0faeb0b2f4b903e2c67a0c3bf0de
---
>    # digest: sha256:1f4f402b9c14f3ae92b11ada1dfe9893a88f0faeb0b2f4b903e2c67a0c3bf0de
47c47
<   hostNetwork: false
---
>   hostNetwork: true
53c53
<     enabled: false
---
>     enabled: true
133c133
<   kind: Deployment
---
>   kind: DaemonSet
379c379
<     type: LoadBalancer
---
>     type: NodePort
388,389c388,389
<       http: ""
<       https: ""
---
>       http: "32080"
>       https: "32443"
449c449
<     enabled: true
---
>     enabled: false

授权和认证机制

认证会的几个要素
1、用户/账号。
2、登录时认证账号 cyylog
3、查看账号权限
这就涉及到角色、权限、用户和角色绑定— RBAC
4、根据权限决定是否可以访问

K8S里两种账户类型

UserCount —– 用户账号

也就是集群外部访问时使用的用户。最常见的就是kubectl命令就是作为kubernetes-admin用户来执行,k8s本身不记录这些账号.

认证的方式:
今天我们先学习默认认证方式:客户端证书

创建客户端证书
首先假设你装好了openssl (没装执行 sudo yum install openssl  openssl-devel)

   1、创建一个文件夹叫做 ua/cyylog
   2、cd 到 ua/cyylog 目录下
   3、执行
  1)openssl genrsa -out client.key 2048    (这一步是生成客户端私钥)
  2)openssl req -new -key client.key -out client.csr -subj "/CN=cyylog"
  (根据私钥生成csr, /CN指定了用户名cyylog)
  3、sudo openssl x509 -req -in client.csr -CA /etc/kubernetes/pki/ca.crt -CAkey /etc/kubernetes/pki/ca.key -CAcreateserial -out client.crt -days 365
(根据k8s的CA证书生成我们用户的客户端证书)

安装Helm、nginx-ingress

Helm

地址:https://github.com/helm/helm/releases/tag/v3.4.0

nginx-ingress
一 、安装报错
1、helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
2、一定要先随便装下
     helm install my-nginx ingress-nginx/ingress-nginx 

   然后肯定会报错,然后 两条命令
  1、kubectl logs  pod名称
  2、kubectl describe pod 你的pod名称  (这里会看到具体的错误)

  像我这里 就是 k8s.gcr.io/ingress-nginx/controller:v0.41.2  这个镜像无法下载

Events:
  Type     Reason     Age                    From               Message
  ----     ------     ----                   ----               -------
  Normal   Scheduled                default-scheduler  Successfully assigned default/my-nginx-ingress-nginx-controller-6f59b94645-28qn4 to node2
  Normal   Pulling    2m39s (x4 over 4m50s)  kubelet, node2     Pulling image "k8s.gcr.io/ingress-nginx/controller:v0.41.2@sha256:1f4f402b9c14f3ae92b11ada1dfe9893a88f0faeb0b2f4b903e2c67a0c3bf0de"
  Warning  Failed     2m24s (x4 over 4m35s)  kubelet, node2     Failed to pull image "k8s.gcr.io/ingress-nginx/controller:v0.41.2@sha256:1f4f402b9c14f3ae92b11ada1dfe9893a88f0faeb0b2f4b903e2c67a0c3bf0de": rpc error: code = Unknown desc = Error response from daemon: Get https://k8s.gcr.io/v2/: net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)
  Warning  Failed     2m24s (x4 over 4m35s)  kubelet, node2     Error: ErrImagePull
  Normal   BackOff    118s (x6 over 4m34s)   kubelet, node2     Back-off pulling image "k8s.gcr.io/ingress-nginx/controller:v0.41.2@sha256:1f4f402b9c14f3ae92b11ada1dfe9893a88f0faeb0b2f4b903e2c67a0c3bf0de"
  Warning  Failed     103s (x7 over 4m34s)   kubelet, node2     Error: ImagePullBackOff
[cyylog@master src]$  helm delete my-nginx 
二 、 解决方法
于是执行:
  docker pull giantswarm/ingress-nginx-controller:v0.41.2
然后改tag
 docker tag giantswarm/ingress-nginx-controller:v0.41.2   k8s.gcr.io/ingress-nginx/controller:v0.41.2
删之前的tag 
  docker rmi giantswarm/ingress-nginx-controller:v0.41.2

注意:各个节点都要执行
然后删掉刚才的安装  helm delete my-nginx ,然后再继续其他内容



Digest: sha256:8aa4fda472ec83ae59fe0ce9720684d769ed277ff9bdcbb0169178dc9d1f8e85
Status: Downloaded newer image for giantswarm/ingress-nginx-controller:v0.41.2
docker.io/giantswarm/ingress-nginx-controller:v0.41.2
[cyylog@master src]$ 

三 、再次安装

下载chart到本地
helm fetch ingress-nginx/ingress-nginx
修改部分内容后再次安装

helm install my-nginx ingress-nginx    -n my-nginx-ingress

更新用的是如下命令(下面用到)
helm upgrade my-nginx ingress-nginx    -n my-nginx-ingress

PS: 修改配置values.yaml

$ diff 111111.yaml values.yaml
8c8
<     digest: sha256:1f4f402b9c14f3ae92b11ada1dfe9893a88f0faeb0b2f4b903e2c67a0c3bf0de
---
>    # digest: sha256:1f4f402b9c14f3ae92b11ada1dfe9893a88f0faeb0b2f4b903e2c67a0c3bf0de
47c47
<   hostNetwork: false
---
>   hostNetwork: true
53c53
<     enabled: false
---
>     enabled: true
133c133
<   kind: Deployment
---
>   kind: DaemonSet
379c379
<     type: LoadBalancer
---
>     type: NodePort
388,389c388,389
<       http: ""
<       https: ""
---
>       http: "32080"
>       https: "32443"
449c449
<     enabled: true
---
>     enabled: false

授权和认证机制

认证会的几个要素
1、用户/账号。
2、登录时认证账号 cyylog
3、查看账号权限
这就涉及到角色、权限、用户和角色绑定— RBAC
4、根据权限决定是否可以访问

K8S里两种账户类型

UserCount —– 用户账号

也就是集群外部访问时使用的用户。最常见的就是kubectl命令就是作为kubernetes-admin用户来执行,k8s本身不记录这些账号.

认证的方式:
今天我们先学习默认认证方式:客户端证书

创建客户端证书
首先假设你装好了openssl (没装执行 sudo yum install openssl  openssl-devel)

   1、创建一个文件夹叫做 ua/cyylog
   2、cd 到 ua/cyylog 目录下
   3、执行
  1)openssl genrsa -out client.key 2048    (这一步是生成客户端私钥)
  2)openssl req -new -key client.key -out client.csr -subj "/CN=cyylog"
  (根据私钥生成csr, /CN指定了用户名cyylog)
  3、sudo openssl x509 -req -in client.csr -CA /etc/kubernetes/pki/ca.crt -CAkey /etc/kubernetes/pki/ca.key -CAcreateserial -out client.crt -days 365
(根据k8s的CA证书生成我们用户的客户端证书)
用户账号

授权和认证机制

用户账号 : 使用证书初步请求API、设置上下文

     上一步 我们生成一个客户端证书   :用户名是 cyylog 。

    最简单的请求 方式还是:
1、kubectl get endpoints  查看下endpoint
2、curl --cert ./client.crt --key ./client.key --cacert /etc/kubernetes/pki/ca.crt -s https://192.168.42.140:6443/api

 其中 可以用 --insecure 代替 --cacert /etc/kubernetes/pki/ca.crt 从而忽略服务端证书验证

证书反解

如果你忘了证书设置的CN(Common name)是啥 可以用下面的命令搞定
openssl x509 -noout -subject -in client.crt

接下来我们要干的事

 把:
    client.crt加入到~/.kube/config,执行kubectl命令时切换成我们的用户(虽然现在其实没啥权限)

   kubectl config --kubeconfig=/home/cyylog/.kube/config set-credentials cyylog  --client-certificate=/home/cyylog/ua/cyylog/client.crt --client-key=/home/cyylog/ua/cyylog/client.key

   这一步把用户设置进去了

//创建一个context(上下文)

kubectl config --kubeconfig=/home/cyylog/.kube/config set-context user_context --cluster=kubernetes  --user=cyylog

指定当前上下文是:
 kubectl config --kubeconfig=/home/cyylog/.kube/config use-context user_context
入门Role和RoleBinding

授权和认证机制: 入门Role和RoleBinding、创建一个角色

Role (角色)
它可以包含一堆权限。用于授予对单个命名空间的资源访问

RoleBinding
顾名思义,将用户和角色进行绑定

kubectl get role –all-namespaces

上一段:
我们把 cyylog 这个用户(usercount)加入到 kubectl config中

并且用了
 kubectl config  use-context user_context
来切换上下文。

切回管理员可以这么干:
 kubectl config  use-context kubernetes-admin@kubernetes

Next

我们希望让 cyylog 这个用户能查看pod 
我们创建一个文件叫做:mypod_role.yaml
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  namespace: default
  name: mypod
rules:
- apiGroups: ["*"]
  resources: ["pods"]
  verbs: ["get", "watch", "list"]
关于apiversion

文档地址:(不要网上搜到啥就贴啥)
https://v1-18.docs.kubernetes.io/docs/reference/generated/kubernetes-api/v1.18/#role-v1-rbac-authorization-k8s-io

关于资源
可以用 这个命令查看:
    kubectl api-resources -o wide

 譬如role有 对应的操作如下
create  delete  deletecollection   get     list        patch        update   watch
创建     删除       批量删除          获取  列表    合并变更    更新     监听

接下来执行

执行下面的内容,则完成角色的创建
kubectl apply -f mypod_role.yaml

kubectl get role -n default ----查看下

kubectl delete role mypod   (不加-n  默认就是default)
RoleBinding

用户和角色进行绑定

kubectl get role

第一种方式: 命令行


   kubectl create rolebinding mypodbinding  -n default  --role mypod --user cyylog

 接下来可以 切换
1、我们的普通用户是  kubectl config use-context user_context
2、管理员是: kubectl config use-context  kubernetes-admin@kubernetes

第二种方式:

创建一个文件 譬如叫做mypod_rolebinding.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  creationTimestamp: null
  name: mypodrolebinding
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: mypod
subjects:
- apiGroup: rbac.authorization.k8s.io
  kind: User
  name: cyylog
CluterRole

ClusterRole和ClusterRoleBinding

​ 可以管理集群中多个 namespace,就需要使用到clusterrole
​ 绑定既可以使用RoleBinding,也可以使用ClusterRoleBinding ( 两者效果不同)

之前创建Role的文件

kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  namespace: default
  name: mypod
rules:
- apiGroups: ["*"]
  resources: ["pods"]
  verbs: ["get", "watch", "list"]

改一下

kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: mypod-cluster
rules:
- apiGroups: ["*"]
  resources: ["pods"]
  verbs: ["get", "watch", "list"]

然后绑定:

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: mypodrolebinding
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: mypod
subjects:
- apiGroup: rbac.authorization.k8s.io
  kind: User
  name: cyylog


改一下:
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: mypodrolebinding-cluster
  namespace: kube-system
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: mypod-cluster
subjects:
- apiGroup: rbac.authorization.k8s.io
  kind: User
  name: cyylog
clusterrole+clusterrolebinding

可以管理集群中多个 namespace,就需要使用到clusterrole
绑定既可以使用RoleBinding,也可以使用ClusterRoleBinding ( 两者效果不同)

1、 上上一段:role+rolebinding
2、 上一段课我们:clusterrole+rolebinding
3、 这节我们学习clusterrole+clusterrolebinding

首先我们把上一段课的role、rolebinding都删掉

删除命令


 1、 kubectl delete rolebinding mypodrolebinding-cluster -n kube-system
 2、 kubectl delete rolebinding mypodrolebinding
 3、 kubectl delete role mypod

只保留一个 clusterrole --------mypod-cluster

改一下文件

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: mypod-clusterrolebinding
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: mypod-cluster
subjects:
 - apiGroup: rbac.authorization.k8s.io
   kind: User
   name: cyylog
UserAccount

使用token的方式请求API

1、前面我们学习到了创建UserAccount 。并使用证书的方式请求
2、role+rolebinding
3、clusterrole+clusterrolebinding

那么其实 假设我们要请求API, 还可以使用token的方式
首先先试一下

 curl https://192.168.42.140:6443   这是不可以访问的


接下来我们设置一个 token (现在是我们上面的普通用户cyylog)
1、用这个命令生成token 
   head -c 16 /dev/urandom | od -An -t x | tr -d ' '         (' '之间有个空格)
    kubectl config set-credentials cyylog --token=5bd8fce499b79b23bfdef72afb8d7bda
找个获取pod的API试一试

https://v1-18.docs.kubernetes.io/docs/reference/generated/kubernetes-api/v1.18/#role-v1-rbac-authorization-k8s-io

还是看这个文档

curl -H "Authorization: Bearer 5bd8fce499b79b23bfdef72afb8d7bda" https://192.168.42.140:6443/api/v1/namespaces/default/pods --insecure

对比一下 (默认情况下还是没用的)

curl --cert ./client.crt --key ./client.key --cacert /etc/kubernetes/pki/ca.crt -s https://192.168.42.140:6443/api/v1/namespaces/default/pods

修改api-server的启动参数

首先创建 
sudo vi /etc/kubernetes/pki/token_auth 
塞入如下内容
5bd8fce499b79b23bfdef72afb8d7bda,cyylog,1001

然后是修改api-server启动参数
sudo vi /etc/kubernetes/manifests/kube-apiserver.yaml

加入  --token-auth-file=/etc/kubernetes/pki/token_auth
ServiceAccount
SA入门(1):创建账号

前面

1、我们学习到了创建UserAccount 。并使用证书、token的方式请求
2、role+rolebinding
3、clusterrole+clusterrolebinding

创建一个ServiceAccount

查看 是这样的:
   kubectl get sa -n xxxx  (不写-n 就是默认default)

用命令创建一个
  kubectl  create  serviceaccount   mysa

     每个namespace都会有一个默认的 default账号,且sa局限在自己所属的namespace中。而UserAccount是可以跨ns的


其他步骤

 kubectl describe sa mysa 
你还会发现

k8s会在secrets 里面保存一个token

通过kubectl describe secret mysa-token-sk67q (改成你自己的)

第二种方式:

kubectl  create  serviceaccount  mysa  -o  yaml  --dry-run=client

进阶一下,可以这样
kubectl  create  serviceaccount  mysa  -o  yaml  --dry-run=client > mysa.yaml
SA入门(2):赋予权限

前面:

我们创建了一个sa账号,叫做mysa。现在尝试用sa账号访问 api

装个工具叫做jq
是一个轻量级的json处理命令。可以对json数据进行分片、过滤、映射和转换 jq . 对json数据进行格式化输出

sudo yum install jq -y

绑定角色

在此之前,我们创建一个 clusterrole叫做 mypod-cluster

此权限 可以查看 pods列表

kubectl create clusterrolebinding mysa-crb --clusterrole=mypod-cluster --serviceaccount=default:mysa

分解命令

分解命令
1、kubectl get sa  mysa
2、 kubectl get sa  mysa -o json
3、kubectl get sa  mysa -o json | jq  '.secrets[0].name'
4、kubectl get sa  mysa -o json | jq -Mr '.secrets[0].name'
假设得到的值是 mysa-token-x6ct6
5、kubectl get secret  mysa-token-x6ct6
6、kubectl get secret  mysa-token-x6ct6 -o json | jq -Mr '.data.token'
7、 kubectl get secret  mysa-token-x6ct6 -o json | jq -Mr '.data.token' | base64 -d

连起来

kubectl get secret  $(kubectl get sa  mysa -o json | jq -Mr '.secrets[0].name'
) -o json | jq -Mr '.data.token' | base64 -d

设置成一个变量
mysatoken=$(kubectl get secret  $(kubectl get sa  mysa -o json | jq -Mr '.secrets[0].name'
) -o json | jq -Mr '.data.token' | base64 -d)

请求:
curl -H "Authorization: Bearer $mysatoken" --insecure  https://192.168.42.140:6443/api/v1/namespaces/default/pods 
SA入门(3):访问方式一

在POD里访问k8s API(token的方式)

为了简单

apiVersion: apps/v1
kind: Deployment
metadata:
  name: myngx
spec:
  selector:
    matchLabels:
      app: nginx
  replicas: 1
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: nginxtest
          image: nginx:1.18-alpine
          imagePullPolicy: IfNotPresent
          ports:
            - containerPort: 80

接下来执行

kubectl get pod 

可以看到pod列表 ,然后我们 进入 该容器

kubectl exec -it  myngx-58bddf9b8d-qmdq7 -- sh

记录几个知识点

echo $KUBERNETES_SERVICE_HOST   
echo $KUBERNETES_PORT_443_TCP_PORT

于是 
  echo $KUBERNETES_SERVICE_HOST:$KUBERNETES_PORT_443_TCP_PORT

保存到环境变量中:

 1、TOKEN=`cat /var/run/secrets/kubernetes.io/serviceaccount/token`
2、APISERVER="https://$KUBERNETES_SERVICE_HOST:$KUBERNETES_PORT_443_TCP_PORT"

请求试一试

 curl --header "Authorization: Bearer $TOKEN" --insecure -s $APISERVER/api

我们可以看到 上面是可以的,但下面不可以,因为default账号没有列出pods的权限
curl --header "Authorization: Bearer $TOKEN" --insecure -s $APISERVER/api/v1/namespaces/default/pods 

修改我们deployment

 spec:
      serviceAccountName: mysa
      containers:
        - name: nginxtest
          image: nginx:1.18-alpine
          imagePullPolicy: IfNotPresent
          ports:
SA入门(3):访问方式二

在POD里访问k8s API(token+证书的方式)

更常用的方式是直接用证书

证书的位置在:
/var/run/secrets/kubernetes.io/serviceaccount/ca.crt

上面讲的token的位置在
cat /var/run/secrets/kubernetes.io/serviceaccount/token


前面
curl --header "Authorization: Bearer $TOKEN"  -s $APISERVER/api/v1/namespaces/default/pods 

现在
curl --header "Authorization: Bearer $TOKEN" --cacert  /var/run/secrets/kubernetes.io/serviceaccount/ca.crt   $APISERVER/api/v1/namespaces/default/pods 

Pod 和 Deployment

本章节:Pod入门、看文档的方式、创建Pod

文档地址:https://v1-18.docs.kubernetes.io/docs/reference/generated/kubernetes-api/v1.18/#pod-v1-core

Pod

最小调度单位(pod)好处:
1、 方便部署、扩展和收缩、方便调度等,反正各种方便

2、Pod中的容器共享数据和网络空间,统一的资源管理与分配(想想第二章我们讲的ServiceCount)

pause容器作用

1、扮演Pid=1的,回收僵尸进程

2、基于Linux的namespace的共享

rPuUIA.png

Pod基本操作

Pod基本操作、创建一个多容器的Pod(上)

创建第一个Pod

apiVersion: v1
kind: Pod
metadata:
  name: myngx
spec:
  containers:
  - name: ngx
    image: "nginx:1.18-alpine"

顺手学习几个命令

kubectl describe pod xxxx  查看pod详细

kubectl logs   xxx 查看日志

kubectl exec -it xxx  -- sh  //进入pod

多容器

apiVersion: v1
kind: Pod
metadata:
  name: myngx
spec:
  containers:
  - name: ngx
    image: "nginx:1.18-alpine"
  - name: alpine
    image: "alpine:3.12"

发现,alpine 容器没有启动,未启动command

apiVersion: v1
kind: Pod
metadata:
  name: myngx
spec:
  containers:
  - name: ngx
    image: "nginx:1.18-alpine"
  - name: alpine
    command: ["sh","-c","echo this is second && sleep 3600"]
    image: "alpine:3.12"
Volumes 配置数据卷

配置数据卷:挂载主机目录、排坑方式

文档
https://kubernetes.io/zh/docs/concepts/storage/volumes/

基本格式
.......... (略)
spec:
  containers:
  - name: ngx
    image: "nginx:1.18-alpine"
    volumeMounts:
    - name: mydata
      mountPath: /data

  volumes:
    - name: mydata
      hostPath:
        path: /data
        type: Directory
基本写法
apiVersion: v1
kind: Pod
metadata:
  name: myngx
spec:
  containers:
  - name: ngx
    image: "nginx:1.18-alpine"
    volumeMounts:
    - name: mydata
      mountPath: /data
  - name: alpine
    command: ["sh","-c","echo this is second && sleep 3600"]
    image: "alpine:3.12"
  volumes:
  - name: mydata
    hostPath:
      path: /data/cyylog/data
      type: Directory
Deployment

本小节讲述 Pod和Deployment基本区别、创建deployment

Pods:
  1、运行一组容器 、适合一次性开发
  2、很少直接用于生产

Deployment
1、运行一组相同的Pod(副本水平扩展)、滚动更新
2、适合生产

总结为:Deployment通过副本集管理和创建POD。

myngx.yaml文件

apiVersion: apps/v1
kind: Deployment
metadata:
  name: myngx
spec:
  selector:
    matchLabels:
      app: nginx
  replicas: 1
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: ngx
          image: nginx:1.18-alpine
          imagePullPolicy: IfNotPresent
两个容器共享文件夹

文档
https://kubernetes.io/zh/docs/concepts/storage/volumes/

两个节点分别写入挂载点
volumeMounts:
    - name: sharedata
      mountPath: /data

关键点

 volumes:
  - name:  sharedata
    emptyDir: {}

    同一个pod内的容器都能读写EmptyDir中 文件。常用于临时空间、多容器共享,如日志或者tmp文件需要的临时目录

myngx.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: myngx
spec:
  selector:
    matchLabels:
      app: nginx
  replicas: 1
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: ngx
          image: nginx:1.18-alpine
          imagePullPolicy: IfNotPresent
          volumeMounts:
            - name: sharedata
              mountPath: /data
        - name: alpine
          image: alpine:3.12
          imagePullPolicy: IfNotPresent
          command: ["sh","-c","echo this is alpine && sleep 36000"]
          volumeMounts:
            - name: sharedata
              mountPath: /data
      volumes:
        - name:  sharedata
          emptyDir: {}
init容器

​ Init 容器是一种特殊容器,在 Pod 内的应用容器启动之前运行。Init 容器可以包括一些应用镜像中不存在的实用工具和安装脚本

Init 容器与普通的容器非常像,除了如下两点:
它们总是运行到完成。
每个都必须在下一个启动之前成功完成。

​ 如果 Pod 的 Init 容器失败,kubelet 会不断地重启该 Init 容器直到该容器成功为止。 然而,如果 Pod 对应的 restartPolicy 值为 “Never”,Kubernetes 不会重新启动 Pod。
文档地址:
https://kubernetes.io/zh/docs/concepts/workloads/pods/init-containers/

基本配置
 initContainers:
  - name: init-mydb
    image: alpine:3.12
    command: ['sh', '-c', 'echo wait for db && sleep 35 && echo done']

具体场景以后我们再演示:
1、譬如 ping db
2、譬如控制服务启动顺序

myngx.yaml案例文件

apiVersion: apps/v1
kind: Deployment
metadata:
  name: myngx
spec:
  selector:
    matchLabels:
      app: nginx
  replicas: 1
  template:
    metadata:
      labels:
        app: nginx
    spec:
      initContainers:
        - name: init-mydb
          image: alpine:3.12
          command: ['sh', '-c', 'echo wait for db && sleep 35 && echo done']
      containers:
        - name: ngx
          image: nginx:1.18-alpine
          imagePullPolicy: IfNotPresent
          volumeMounts:
            - name: sharedata
              mountPath: /data
        - name: alpine
          image: alpine:3.12
          imagePullPolicy: IfNotPresent
          command: ["sh","-c","echo this is alpine && sleep 36000"]
          volumeMounts:
            - name: sharedata
              mountPath: /data
      volumes:
        - name:  sharedata
          emptyDir: {}

DeploymentConfigMap

本章节讲述 ConfigMap 基本创建、环境变量引用

基本概念

​ ConfigMap 是一种 API 对象,用来将非机密性的数据保存到健值对中。使用时可以用作环境变量、命令行参数或者存储卷中的配置文件。

​ ConfigMap 将您的环境配置信息和 容器镜像 解耦,便于应用配置的修改。当您需要储存机密信息时可以使用 Secret 对象。

使用的场景
    1、 容器 entrypoint 的命令行参数
    2、 容器的环境变量
    3、 映射成文件
    4、 编写代码在 Pod 中运行,使用 Kubernetes API 来读取 ConfigMap
基本命令
获取列表
  kubectl get cm

 创建一个cm 
apiVersion: v1
kind: ConfigMap
metadata:
  name: mycm
data:
  # 每一个键对应一个简单的值,以字符串的形式体现
  username: "cyylog"
  userage: "19"


也可以这样 
。。。。。
data:
  username: "cyylog"
  userage: "19“
  user.info: |
    name=cyylog
    age=19

接下来

删掉之前的deployment (myngx)

写入  (和image同级)
   env:
           - name: USER_NAME
             valueFrom:
                configMapKeyRef:
                  name: mycm           #  ConfigMap的名称
                  key: username # 需要取值的键

mycm.yaml

apiVersion: v1
kind: ConfigMap
metadata:
  name: mycm
data:
  # 每一个键对应一个简单的值,以字符串的形式体现
  username: "cyylog"
  userage: "19"
  user.info: |
    name=cyylog
    age=19

myngx.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: myngx
spec:
  selector:
    matchLabels:
      app: nginx
  replicas: 1
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: ngx
          image: nginx:1.18-alpine
          imagePullPolicy: IfNotPresent
          env:
            - name: TEST
              value: testvalue
            - name: USERNAME
              valueFrom:
                configMapKeyRef:
                  name: mycm           #  ConfigMap的名称
                  key: username # 需要取值的键
映射成文件
volumeMounts:
            - name: cmdata
              mountPath: /data

然后写卷
 https://kubernetes.io/zh/docs/concepts/storage/volumes
 volumes:
        - name: cmdata
          configMap:
            name: mycm
            items:
              - key: user.info
                path: user.txt

myngx.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: myngx
spec:
  selector:
    matchLabels:
      app: nginx
  replicas: 1
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: ngx
          image: nginx:1.18-alpine
          imagePullPolicy: IfNotPresent
          volumeMounts:
            - name: cmdata
              mountPath: /data
          env:
            - name: TEST
              value: testvalue
            - name: USERNAME
              valueFrom:
                configMapKeyRef:
                  name: mycm           #  ConfigMap的名称
                  key: username # 需要取值的键
      volumes:
        - name: cmdata
          configMap:
            name: mycm
            items:
              - key: user.info
                path: user.txt
subpath

上一个节

volumeMounts:
            - name: cmdata
              mountPath: /data

然后写卷
 https://kubernetes.io/zh/docs/concepts/storage/volumes
 volumes:
        - name: cmdata
          configMap:
            name: mycm
            items:
              - key: user.info
                path: user.txt

如果我们不指定具体的key

  volumes:
        - name: cmdata
          configMap:
            name: mycm

这时你会发现,所有文件都被 映射进去了,文件名就是key名

如果我希望:
不指定key 。也想挂载其中一个配置

文档:
https://kubernetes.io/zh/docs/concepts/storage/volumes/#using-path

用于指定所引用的卷(volumes)内的子路径,而不是其根路径

修改点

 volumeMounts:
        - mountPath: /data/user.txt
          name: cmdata
          subPath: user.info

这个不变
 volumes:
        - name: cmdata
          configMap:
            name: mycm

myngx.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: myngx
spec:
  selector:
    matchLabels:
      app: nginx
  replicas: 1
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: ngx
          image: nginx:1.18-alpine
          imagePullPolicy: IfNotPresent
          volumeMounts:
            - name: cmdata
              mountPath: /data/user.txt
              subPath: user.info
          env:
            - name: TEST
              value: testvalue
            - name: USERNAME
              valueFrom:
                configMapKeyRef:
                  name: mycm           #  ConfigMap的名称
                  key: username # 需要取值的键
      volumes:
        - name: cmdata
          configMap:
            defaultMode: 0655
            name: mycm        
#            items:
#              - key: user.info
#                path: user.txt

Deployment和Secret

入门和无脑创建(Opaque)

根据官方定义

​ Secret 对象类型用来保存敏感信息,例如密码、OAuth 令牌和 SSH 密钥。 将这些信息放在 secret 中比放在 Pod 的定义或者 容器镜像 中来说更加安全和灵活。 参阅 Secret 设计文档 获取更多详细信息。

​ Secret 是一种包含少量敏感信息例如密码、令牌或密钥的对象。 这样的信息可能会被放在 Pod 规约中或者镜像中。 用户可以创建 Secret,同时系统也创建了一些 Secret。

关键词
1、敏感、少量
2、安全和灵活

类型

65K9jx.png

先来一把配置

apiVersion: v1
kind: Secret
metadata:
  name: mysecret
type: Opaque
data:
  user: "cyylog"
  pass: "123"

试一下 对还是不对?

根据提示

我们需要 先base64编码

最简单的方式 使用命令直接搞定

echo cyylog | base64 && echo 123 | base64

把得到的值替换即可

命令获取secret内容、挂载文件
查看命令
 上一步用到了
    kubectl get secret mysecret -o yaml

其实 还可以
kubectl get secret mysecret -o json
secret进行basic-auth认证
(1):手工配置

类型

6OVou9.png

nginx 认证

location / {
  auth_basic      "xxxxooooo";
  auth_basic_user_file conf/htpasswd;
}
其中密码 我们常用的是 
    通过apache的工具htpasswd或者openssl passwd命令生成

htpasswd提供了一个变种的MD5加密算法(apr1),这里不深究

安装工具

sudo yum -y install httpd-tools
Apache的Web服务器内置的工具,用于创建和更新储存用户名和用户基本认证的密码文件

创建一个密码文件  
htpasswd -c auth cyylog
这时产生了一个 auth文件

再添加一个  用户(此时不用-c参数)
htpasswd  auth lisi

我们做成一个ConfigMap

名称叫做bauth
然后把刚才的内容 拷贝进去

注意点:我们课程使用的镜像是 nginx:1.18-alpine

它的 默认配置文件在/etc/nginx/nginx.conf

其中 主配置文件引用了 /etc/nginx/conf.d/default.conf 文件 

拷贝并修改

server {
    listen       80;
    server_name  localhost;
    location / {
       auth_basic      "test auth";
       auth_basic_user_file /etc/nginx/basicauth;
        root   /usr/share/nginx/html;
        index  index.html index.htm;
    }
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }
}

挂载

 volumeMounts:
            - name: nginxconf
              mountPath: /etc/nginx/conf.d/default.conf
              subPath: ngx
            - name: basicauth
              mountPath: /etc/nginx/basicauth
              subPath: auth

volumes:
        - name: nginxconf
          configMap:
            defaultMode: 0655
            name: nginxconfig
        - name: basicauth
          configMap:
              defaultMode: 0655
              name: bauth

访问测试

curl --basic -u cyylog:123456  http://10.42.2.52
(2):使用secret挂载

前面

location / {
  auth_basic      "xxxxooooo";
  auth_basic_user_file conf/htpasswd;
}    

其中我们映射了 一个configMap来 实现 。

用文件的方式导入

kubectl  create secret generic secret-basic-auth  --from-file=auth

访问测试

curl --basic -u cyylog:123456  http://10.42.2.52
拉取私有镜像、创建Docker Secret

首先去
https://hub.docker.com/signup

注册 并且登录 。 这个过程自行搞定

然后 随便

1、docker pull alpine:3.12 

2、docker login --username=cyylog  (输入密码)

3、docker tag alpine:3.12 cyylog/myalpine:3.12

创建私有镜像库

https://hub.docker.com/repository/create

6OqYU1.png

发布

docker push cyylog/myalpine:3.12 


稍等片刻 后 我们一个 简单的私有镜像就好了 

接下来 把我们刚才打标签的tag给删掉 
docker rmi cyylog/myalpine:3.12

写个deployment

apiVersion: apps/v1
kind: Deployment
metadata:
  name: myalpine
spec:
  selector:
    matchLabels:
      app: myalpine
  replicas: 1
  template:
    metadata:
      labels:
        app: myalpine
    spec:
      containers:
        - name: alpine
          image: cyylog/myalpine:3.12
          imagePullPolicy: IfNotPresent
          command: ["sh","-c","echo this is alpine && sleep 36000"]

接下来就要创建secret

kubectl create secret docker-registry dockerreg \
  --docker-server=https://index.docker.io/v1/\
  --docker-username=cyylog \
  --docker-password=pass123 \
  --docker-email=cyylog@test.com

内容解码后

6XSVh9.png

kubectl get secret  dockerreg -o jsonpath={.data.*} | base64 -d

加入配置

imagePullSecrets:
    - name: dockerreg

Deployment和Service

创建一个最基本的Service、ClusterIP
Service

作用:
一句话:提供负载均衡和服务自动发现

我们先弄个一个ConfigMap

apiVersion: v1
data:
  h1: this is h1
  h2: this is h2
kind: ConfigMap
metadata:
    name: html

写个**deployment**

apiVersion: v1
kind: Service
metadata:
  name: nginx-svc
spec:
  type: ClusterIP
  ports:
    - port: 80
      targetPort: 80
  selector:  #service通过selector和pod建立关联
    app: nginx

**服务类型—ClusterIP

ClusterIP:通过集群的内部 IP 暴露服务,选择该值时服务只能够在集群内部 访问。 这也是默认的 ServiceType。

宿主机访问k8s的Service的基本方法

安装一个工具

sudo yum install  bind-utils  -y

记下来我们执行
nslookup nginx-svc

处理办法

# kubectl get svc -n kube-system

10.43.0.10 

# sudo vi /etc/resolv.conf

nameserver 10.43.0.10
search default.svc.cluster.local svc.cluster.local

/etc/resolv.conf

用于设置DNS服务器IP地址、DNS域名和设置主机的域名搜索顺序

我们加一个进去

然后执行 nslookup nginx-svc.default.svc.cluster.local

无头Service初步入门

无头服务

所谓的无头服务
通过指定 ClusterIP的值为“None”来创建 Headless Service

具体配置

先删掉  nginx-svc 这个service

apiVersion: v1
kind: Service
metadata:
  name: nginx-svc
spec:
  clusterIP: "None"
  ports:
    - port: 80
      targetPort: 80
  selector:  #service通过selector和pod建立关联
    app: nginx

作用

有些程序 需要自己来决定到底 使用哪个IP
譬如golang 可以使用 net.LookupIP(“服务名”),来获取 IP ,然后自己来决定到底使用哪个

StatefulSet 状态下。POD互相访问#### PV和PVC

创建PV、Local方式、基本设置
PV

全称是:PersistentVolume(持久化卷),是对底层的共享存储的一种抽象, 由管理员进行创建和配置。

然后由 卷插件 如local、NFS 等具体的底层技术来实现

官网地址:https://kubernetes.io/zh/docs/concepts/storage/persistent-volumes/#types-of-persistent-volumes

创建一个

apiVersion: v1
kind: PersistentVolume
metadata:
  name: local-pv
spec:
  capacity:
    storage: 1Gi
  volumeMode: Filesystem
  accessModes:
     - ReadWriteOnce
  persistentVolumeReclaimPolicy: Delete
  storageClassName: local-storage
  local:
    path: /mnt/disks/ssd1

capacity

它的单位有:
     P,T,G,M,K或 Pi,Ti,Gi,Mi,Ki 区别
   加i的是以1024为换算单位 

如 (1Mi)
1M=1024K=1024×1024byte

1M 则是1000*1000

accessModes

访问模式有:

ReadWriteOnce -- 卷可以被一个节点以读写方式挂载;
ReadOnlyMany -- 卷可以被多个节点以只读方式挂载;
ReadWriteMany -- 卷可以被多个节点以读写方式挂载。

PersistentVolume 对象的回收策略

Retained(保留)、Recycled(回收)或 Deleted(删除)

节点亲和性

之前我们调度节点时用过nodeSelector ,设定标签进行匹配。这种方式过于”粗暴简单”。使用NodeAffinity来进行控制颗粒度更小(对于local模式 ,我们必须要设置)
软策略 (有最好,没有也无所谓)
如果没有满足调度要求的节点的话,就会忽略按正常调度
preferredDuringSchedulingIgnoredDuringExecution
preferredDuringSchedulingRequiredDuringExecution (一旦后面标签改了,有满足条件的节点了,就会重新调度到该节点上)

硬策略

硬策略
如果没有满足条件的节点的话,就不断重试直到满足条件为止

requiredDuringSchedulingIgnoredDuringExecution (如果一开始满足的,后面node标签发生变化了,也无妨,继续运行)

requiredDuringSchedulingRequiredDuringExecution(一旦变了,不符合条件了。则重新选择)

查看标签

kubectl get node --show-labels=true

打标签语法:
kubectl label nodes  =

kubectl label nodes cyylog2 pv=local

删除语法
kubectl label nodes  -
kubectl label nodes cyylog2 pv-

matchExpressions

In: label的值在某个列表中
NotIn:label的值不在某个列表中
Exists:某个label存在
DoesNotExist:某个label不存在
Gt:label的值大于某个值(字符串比较)
Lt:label的值小于某个值(字符串比较) 
创建PVC、初步绑定PV 、POD挂载

复习PV

全称是:PersistentVolume(持久化卷),是对底层的共享存储的一种抽象, 由管理员进行创建和配置。

然后由 卷插件 如local、NFS 等具体的底层技术来实现

(运维 或管理员 ) PVC

PVC(Persistent Volume Claim)

Persistent Volume提供存储资源(并实现)
Persistent Volume Claim 描述需要的存储标准,然后从现有PV中匹配或者动态建立新的资源,最后将两者进行绑定。

好比
PV是提供者,提供存储方式和容量 ( 销售费用1万)

PVC是消费者,消费容量 (它不需要关注用什么技术实现,绑定即可)

绑定方式

PV和PVC中
spec关键字段要匹配 。
storageClassName字段必须一致

PersistentVolume 对象的回收策略

 Retained(保留)、Recycled(回收)或 Deleted(删除)
StorageClass简单入门和创建
StorageClass

理解为创建PV的模板

文档

https://kubernetes.io/zh/docs/concepts/storage/storage-classes/

例子

provisioner:指的是卷插件  (如NFS,local)
reclaimPolicy:  回收策略。 
volumeBindingMode :绑定模式
    Immediate :一旦创建PVC 就绑定
    WaitForFirstConsumer:就是延迟绑定,直到使用该 PVC 的 Pod 被创建
parameters:参数(不同的存储方式有N多个不同参数,这里不讲了。大家自行看文档)

POD自动伸缩(HPA

HPA入门、部署metrics-server
HPA

Pod 水平自动扩缩(Horizontal Pod Autoscaler) 可以

1、基于 CPU 利用率自动扩缩 ReplicationControllerDeploymentReplicaSetStatefulSet 中的 Pod 数量。

2、 除了 CPU 利用率,也可以基于其他应程序提供的自定义度量指标 来执行自动扩缩。

3、 Pod 自动扩缩不适用于无法扩缩的对象,比如 DaemonSet

metrics-server

k8s里。可以通过Metrics-Server服务采集节点和Pod的内存、磁盘、CPU和网络的使用率等

注意:
Metrics API 只可以查询当前的度量数据,并不保存历史数据
Metrics API URI/apis/metrics.k8s.io/
必须部署 metrics-server 才能使用该 API,metrics-server 通过调用 Kubelet Summary API 获取数据

部署方式

官方告诉我们
kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml

这里面有个镜像干不下来,一些配置也需要修改。

具体附件

### 查看
kubectl top pod    (还可以写node)

### 创建一个
最简单是 使用命令直接创建
kubectl autoscale deployment ngx1 --min=2 --max=5 --cpu-percent=20
限制POD资源、创建HPA

看一段配置

resources:
        requests:
            cpu: "200m"
            memory: "256Mi"
        limits:
           cpu: "400m"
            memory: "512Mi“

 requests来设置各容器需要的最小资源
 limits用于限制运行时容器占用的资源
 1物理核=1000个微核(millicores)      1000m=1CPU

装个工具

sudo yum -y install httpd-tools

里面包含了一个 apache ab 工具  做简单压测

ab -n 10000 -c 10  http://web1/

创建一个

最简单是 使用命令直接创建
kubectl autoscale deployment web1 --min=1 --max=5 --cpu-percent=20
yaml的方式创建HPA
几个API版本

kubectl api-versions | grep autoscaling

autoscaling/v1 #只支持通过cpu伸缩
autoscaling/v2beta1 #支持通过cpu、内存 和自定义数据来进行伸缩。
autoscaling/v2beta2 #beta1的进一步 (一般用它)

yaml配置方式
apiVersion: autoscaling/v2beta2
kind: HorizontalPodAutoscaler
metadata:
  name: web1hpa
  namespace: default
spec:
  minReplicas: 1
  maxReplicas: 5
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: web1
  metrics:
    - type: Resource
      resource:
        name: cpu
        target:
          type: Utilization
          averageUtilization: 50   #使用率
    - type: Resource
      resource:
        name: memory
        target:
          type: Utilization
          averageUtilization: 50   #使用率

使用量

 metrics:
    - type: Resource
      resource:
        name: cpu
        target:
          type: AverageValue
          averageValue: 230m   #使用量
    - type: Resource
      resource:
        name: memory
        target:
          type: AverageValue
          averageValue: 400m   #使用量
关于自定义指标

自定义指标 比较主流的方式是使用prometheus

大概有几项需要安装:
node-exporterprometheusexport,收集Node级别的监控数据
prometheus:监控服务端,从node-exporter拉数据并存储为时序数据。
kube-state-metrics:将prometheus中可以用PromQL查询到的指标数据转换成k8s对应的数据
k8s-prometheus-adpater:聚合进apiserver,即custom-metrics-apiserver实现(也可以用自定义CRD来实现)#### CRDController

什么是CRD

​ CRD 是 Kubernetes 的一种资源(CustomResourceDefinition ),允许我们基于它自定义新的资源类型.

值得注意的是:k8s所有的东西都叫做资源(Resource)

CRD就是 我们对自定义资源的定义


 上一篇
traefik notes traefik notes
快速上手traefik速学实战traefik是什么 Træfɪk 是一个为了让部署微服务更加便捷而诞生的现代HTTP反向代理、负载均衡工具。 它支持多种后台 (Docker, Swarm, Kubernetes, Marathon, Me
2021-04-10
下一篇 
kubectl 命令自动补全 kubectl 命令自动补全
kubectl 命令自动补全 一.简介在k8s 1.3版本之前,设置kubectl命令自动补全是通过以下的方式:source ./contrib/completions/bash/kubectl 但是在k8s 1.3版本,源码contrib
2021-01-01
  目录