安装Helm、nginx-ingress
Helm
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
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试一试
还是看这个文档
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的共享
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 配置数据卷
配置数据卷:挂载主机目录、排坑方式
基本格式
.......... (略)
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
两个容器共享文件夹
两个节点分别写入挂载点
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: {}
Deployment
和ConfigMap
本章节讲述
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、安全和灵活
类型
先来一把配置
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):手工配置
类型
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
发布
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
内容解码后
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
利用率自动扩缩ReplicationController
、Deployment
、ReplicaSet
和StatefulSet
中的 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-exporter
:prometheus
的export
,收集Node级别的监控数据prometheus
:监控服务端,从node-exporter
拉数据并存储为时序数据。kube-state-metrics
:将prometheus
中可以用PromQL
查询到的指标数据转换成k8s
对应的数据k8s-prometheus-adpater
:聚合进apiserver
,即custom-metrics-apiserver
实现(也可以用自定义CRD
来实现)####CRD
和Controller
什么是CRD
CRD 是 Kubernetes 的一种资源(CustomResourceDefinition ),允许我们基于它自定义新的资源类型.
值得注意的是:k8s所有的东西都叫做资源(Resource)
CRD就是 我们对自定义资源的定义