1.docker run <image>:<tag> 当引用镜像没有指定tag时,默认的tag为latest。
2.docker build命令会将dockerfile所在目录的文件都传入到docker守护进程所在的机器,如果包含大量文件,速度会变慢。
3.docker镜像的构建是分层的,每一层可以被不通的镜像所复用。
4.docker端口的映射规则:docker run --name kubia-container -p 8070:8080 -d kubia 会绑定本机的8070对应container的8080端口。前面是本机端口。
5.查看更多容器运行信息:docker inspect命令。
6.进入容器,如果容器中包含了bash shell才能执行如下命令:
docker exec -it kubia-container bash
7.pod主机名就是pod的名称。
8.kubectl expose deployment kubia --type=LoadBalancer --name kubia-http 这句话会创建一个loadbalance类型的服务,并且使用阿里云提供的loadbalance创建一个外网地址和端口:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubia-http LoadBalancer 10.206.123.x 39.97.x.x 8080:30708/TCP 9m5s
serviceIP:10.206.123.x
外网IP:39.97.x.x
9.将指定的deploy管理的pod个数扩容:kubectl scale deploy kubia --replicas=2
10.容器被设计为一个容器只运行一个进程。
11.同一个pod内的两个容器共享Linux命名空间,主机名,同一loopback网络
12.同一个cluster内,所有的pod都处于同一个共享地址网络空间内,pod之间没有NAT网关。
13.查看容器日志:日志到达10M的时候,日志会自动轮替,kubectl仅显示最后一次轮替后的条目。如果需要一个pod中有多个container,那么使用kubectl logs podname -c containername -f
14.不通过server层,仅仅通过pod层直接与主机绑定:kubectl port-forward kubia-manual 8888:8080,将主机的8888端口绑定到pod的8080端口。
15.查看pod的标签信息:kubectl get pods --show-labels
16.选择多出一列感兴趣的标签:kubectl get pods --show-labels -L env
17.更改现有标签:kubectl label pod kubia-manual env=debug --overwrite
18.根据标签选择器筛选pod:
(1)筛选出kv为creation_method=manual的pod:kubectl get po -l creation_method=manual
(2)筛选出包含env这个key的pod:kubectl get po -l env
(3)筛选出不包括env这个key的pod:kubectl get po -l '!env'
19.将pod调度到指定满足条件的node上:
(1)kubectl label node gke-xxx-nodename gpu=true
(2)spec:下,
spec:
nodeSelector:
gpu: "true"
20.通过标签选择器删除pod:kubectl delete po -l env=prod -n custom-namespace
21.探针种类:(1)存活探针,(2)就绪探针
22.探针探测方式:HTTP,TCP,EXEC
23.探针使用:放在
spec:
container:
livenessProbe:
httpGet:
path: /
port: 8080
initialDelaySeconds: 15
24.查看前一个崩溃的pod的日志:kubectl logs mypod --previous
25.查看pod为何被重启:kubectl describe po mypod,查看其中的event一级exitcode:exitcode=128+x,x表示终止进程的信号编号。
26.java程序不要使用exec探针,这样会启动新的jvm。
27.水平缩放rc(deploy应该一样):kubectl scale rc kubia --replicas=10
28.replicaset与rc区别:标签选择器更具有表达力,支持in,NotIn,Exists,DoesNotExist
29.DaemonSet:确保符合要求的node上都有一个pod在运行.默认在集群所有的节点上运行.
30.job类型的任务不能使用always的重启策略,应该使用restartPolicy:OnFailure.
31.job类型任务的apiVersion是batch/v1
32.job可以设置并行和串行.比如设置completions:5,parallelism:2将计划有5个pod job任务被调起,同时调起2个并行执行.
33.可以设置job最长工作时间,超过该时间认为失败.activeDeadlineSeconds
34.cronJob:分钟,小时,每月的第几天,月,星期几.
35.可以通过service:port访问服务的地方:登录到pod内部或者在集群内部的node上直接curl
36.如果一个serviceA后面又podA里面运行着微服务,通过登录这个pod后curl这个service的Cluster-ip是访问不到这个pod的service的.只能登录别的pod里.
37.会话亲和性设置:同一个客户端总之请求到同一个pod,亲和性属于TCP,不能基于cookie.
spec:
sessionAffinity: ClientIP
38.客户端pod如何找到server的ip和端口?
(1)如果service先创建,那么客户端可以通过环境变量获取service的ip和端口.
(2)如果service晚于客户端创建,可通过DNS获取service的ip和port
客户端通过"FQDN"来访问service,服务域名通常格式是:servicename.default.svc.cluster.local
39.服务的CLUSTER-IP是无法ping通的.
40.service与pod之间通过endpoint相连,通过命令kubectl get endpoints kubia查看服务kubia后面的pod的ip加端口.service的名称与对应的endpoints资源的名称是一致的.
41.创建nodePort类型的service,及几个port的关系。
apiVersion: v1
kind: Service
metadata:
name: kubia-nodeport
spec:
type: NodePort
ports:
- port: 80 #service层的port
targetPort: 8080 #pod的port
nodePort: 30123 #节点的port
selector:
app: kubia
42.Loadbalance服务是nodeport服务的扩展,几个port的设置与上面nodeport一致。loadbalance的定义:
apiVersion: v1
kind: Service
metadata:
name: kubia-loadbalancer
spec:
type: LoadBalancer
ports:
- port: 80 #service层的port
targetPort: 8080 #pod的port
nodePort: 30005 #节点的port
selector:
app: kubia
查看svc,会看到EXTERNAL-IP这一列会出现一个外网IP。
测试:如果使用nodeport的端口为30123(防火墙没有放开该端口),也不会影响该服务的使用,因为是通过loadbalancer来调用的nodeport,一样可以访问。
但是:EXTERNAL-IP在每次启动的时候是会变化的。
43.nodeport的缺点
外部访问服务时,随机选择的pod不一定在链接的node节点上,可能需要网络跳转,可以通过设置来达到只将请求转发到接受请求的node上的pod上,但是这种方式必须确保所有的node节点都有pod运行。
spec:
externalTrafficPolicy: Local
44.查看本集群的所有ingress资源
kubectl get pod --all-namespaces -o wide|grep ingress
45.通过ingress的方式访问,需要确保域名解析为ingress控制器的IP。通过测试,两次创建同一个ingress,ip地址是一样的!!创建ingress:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: kubia
spec:
rules:
- host: kubia.example.com
http:
paths:
- path: /
backend:
serviceName: kubia-nodeport #后端service的名称
servicePort: 80 #后端service的端口
46.ingress的rules和paths都是数组,可以包含多个条目,一个ingress可以将多个注解和路径映射到多个服务。比如,一个host的多个多个path
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: kubia
spec:
rules:
- host: kubia.example.com
http:
paths:
- path: /kubia
backend:
serviceName: kubia-nodeport
servicePort: 80
- path: /bar
backend:
serviceName: bar
servicePort: 80
47.就绪探针
48.headless服务
该服务不存在cluster-ip,请求dns会返回所有的后端的pod的ip。
apiVersion: v1
kind: Service
metadata:
name: kubia-headless
spec:
clusterIP: None
ports:
- port: 80
targetPort: 8080
selector:
app: kubia
创建后,该service不存在CLUSTER-IP
49.故障排除
(1)service是个虚拟ip,无法ping通的。
(2)就绪探针如果不成功,就不能能成为service的一部分。
(3)使用kubectl get endpoints来检查断点对象。
50.kubectl explain deploy.spec.strategy
更新策略:
51.卷类型
(1)emptyDir:存储临时目录的简单空目录
(2)hostPath:工作节点的文件系统挂载到pod中。
(3)nfs:NFS共享卷
(4)configMap,secret,downwardAPI:将k8s部分资源和集群信息公开给pod的特殊类型的卷。将k8s元数据信息公开给pod使用。
(5)persistentVolumeClain:动态配置持久存储卷。
52.创建两个container共用的卷,/usr/share/nginx/html是nginx的默认路径。
apiVersion: v1
kind: Pod
metadata:
name: fortune
spec:
containers:
- image: luksa/fortune
name: html-generator
volumeMounts:
- name: html
mountPath: /var/htdocs
- image: nginx:alpine
name: web-server
volumeMounts:
- name: html
mountPath: /usr/share/nginx/html
readOnly: true
ports:
- containerPort: 80
protocol: TCP
volumes:
- name: html
emptyDir: {}
默认使用节点的磁盘来当作卷,如果需要使用内存作为卷,修改:
volumes:
- name: html
emptyDir:
midium: Memory
53.hostPath卷:指向节点的文件系统特定的目录或文件,hostPath卷的特性是pod挂了之后,数据不会被删除,如果后续pod再次被调度到该节点,可以继续使用该节点卷的数据。这种方式适用于需要读取主机配置的场景。
54.使用NFS卷
volumes:
- name: mongodb-data
nfs:
server: 1.2.3.4
path: /some/path
55.持久卷和持久卷声明,用户定义持久化卷声明(PVC),指定需要的最低容量要求和访问模式。然后将声明清单提交给k8s api服务器。持久卷声明在pod中,只能由一个用户使用。需要管理员先创建持久化卷,然后用户通过持久化卷声明来挑选管理员创建的符合标准的持久化卷。
(1)创建持久化卷
apiVersion: v1
kind: PersistentVolume
metadata:
name: mongodb-pv
spec:
capacity:
storage: 1Gi
accessMode:
- ReadWriteOnce #单个用户读写模式
- ReadOnlyMany #多个用户只读模式
persistentVolumeReclaimPolicy: Retain #声明被释放后,保留数据
gcePersistentDisk:
pdName: mongodb
fsType: ext4
查看声明的pv:kubectl get pv ,持久卷不属于任何命名空间,跟节点一样属于集群层面的资源。
(2)持久卷声明,这是与pod的创建独立的过程,作为一种独立的PersistentVolumeClaim类型的资源存在,查看pvc命令:kubectl get pvc
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mongodb-pvc
spec:
resources:
requests:
storage: 1Gi
accessModes:
- ReadWriteOnce: #持久化卷的模式必须包含持久化声明卷中的访问模式
storageClassName: ""
accessModes:
RWO:ReadWriteOnce:仅允许单个节点挂载读写
ROX:ReadOnlyMany:允许多个节点挂载只读
RWX:ReadWriteMany:允许多个节点挂载读写
再次查看pv状态:kubectl get pv
可以看到status变为Bound状态,显示已经被绑定。
(3)在pod中使用持久卷声明
apiVersion: v1
kind: Pod
metadata:
name: mongodb
spec:
containers:
- image: mongo
name: mongodb
volumeMounts:
- name: mongodb-data #挂载名称为mongodb-data的volume,下面有声明
mountPath: /data/db #挂载到容器的/data/db下面
ports:
- containerPort: 27017
protocol: TCP
volumes:
- name: mongodb-data
persistentVolumeClaim:
claimName: mongodb-pvc #调用名称为mongodb-pvc的pvc
(4)回收持久化卷
kubectl delete pod mongodb
kubectl delete pvc mongodb-pvc
查看pvc状态:kubectl get pvc
status:pending
查看pv状态:kubectl get pv
status:Released
状态时released而不是avaliable是因为包含了前一个pod的数据。
56.向容器中传递命令行参数
Dockerfile中:
ENTRYPOINT:定义容器被调用时执行的程序。
CMD:传递给entrypoint的参数。
57.shell形式和exec的区别
shell形式:ENTRYPOINT node app.js
exec像是:ENTRYPOINT ["node","app.js"]
exec形式直接运行,而不是利用shell来调用的。可以查看进程列表看出来:
如果直接运行在是node app.js进程;如果是通过shell调用则是:/bin/sh -c node app.js
58.docker中如何传入镜像中脚本参数:
(1)shell脚本:fortuneloop.sh
#! /bin/bash interval=$1
(2)构建镜像
FROM ubuntu:latest
RUN apt-get update; apt-get install -y fortune
ADD fortuneloop.sh /bin/fortuneloop.sh
ENTRYPOINT ["/bin/fortuneloop.sh"]
CMD ["10"]
docker执行的时候,docker run -it docker.io/luksa/fortune:args 15 ,这样就能将15这个参数传给docker去执行了。
59.kubernetes中的执行命令和参数:command和args
command会覆盖docker中定义的ENTRYPOINT,args会覆盖docker中的CMD
60.pod中传参给docker容器
apiVersion: v1
kind: Pod
metadata:
name: fortune2s
spec:
containers:
- image: luksa/fortune:args #使用上面制作好的镜像
args: ["2"] # 将参数传给了镜像
name: html-generator
volumeMounts:
- name html
mountPath: /var/htdocs
...
多参数除了[]形式外,如果是多个参数,表示如下,其中,字符串值不需要引号,数值需要。
args:
- foo
- bar
- "15"
61.环境变量
(1)使用环境变量,如果是个脚本,那么脚本中$INTERNEVAL就可以直接接受环境变量中的INTERNEVAL值,如果是Java程序,就是System.getenv("INTERNEVAL")来获取。
(2)传递给pod:环境变量设置在pod容器中,并非pod级别,这样就可以将INTERVAL这个变量传递给image里使用了。
kind:Pod
spec:
containers:
- image: luksa/fortune:env
env:
- name: INTERVAL
value: "30"
name: html-generator
...
62.在环境变量中引用其他环境变量
env:
- name: FIRST_VAR
value: "foo"
- name: SECOND_VAR
value: "$(FIRST_VAR)bar"
63.configmap通过环境变量的形式或挂载volume的方式,创建一个configmap
kubectl create configmap fortune-config --from-literal=sleep-interval=25
查看configmap:
kubectl get configmap fortune-config -o yaml
apiVersion: v1
data:
sleep-interval: "25"
kind: ConfigMap
metadata:
creationTimestamp: "2019-11-26T01:35:58Z"
name: fortune-config
namespace: default
resourceVersion: "9376362"
selfLink: /api/v1/namespaces/default/configmaps/fortune-config
uid: 18de25d6-0fed-11ea-80c2-00163e164b6a
64.可以使用一个文件或者文件夹来创建configMap:
kubectl create configmap fortune-config --from-file=/a.yaml
文件夹:
kubectl create configmap fortune-config --from-file=/files/
65.给容器传递环境变量
(1)第一种:设置环境变量,使用env+valueFrom字段
apiVersion: v1
kind: Pod
metadata:
name: fortune-env-from-configmap
spec:
containers:
- image: luksa/fortune:env
env:
- name: INTERVAL
valueFrom:
configMapKeyRef:
name: fortune-config
key: sleep-interval
如果引用的configMap不存在,启动会失败,可以标记为configMap为可选的。
configMapKeyRef.optional:true
(2)第二种:读取所有的configmap字段。使用envFrom字段而不是env
spec:
containers:
- image: some-image
envFrom:
- prefix: CONFIG_
configMapRef:
name: my-config-map
CONFIG_为前缀的环境变量都会被读取。这样会匹配到所有,因为所有的环境变量都会包含该前缀。环境变量带有破折号“-”是不合法的,因为无法转换成下划线。
(3)传递configmap条目作为命令行参数
apiVersion: v1
kind: Pod
metadata:
name: fortune-args-from-configmap
spec:
containers:
- image : luksa/fortune:args
env:
- name: INTERVAL #定义环境变量,该环境变量的值从configmap中获取
valueFrom:
configMapKeyRef:
name: fortune-config
key: sleep-interval
args: ["$(INTERVAL)"] #获取上面定义的环境变量INTERVAL传递给容器
(4)configMap卷
configMap卷讲configMap中的每个条目均暴露成一个文件。容器中进程可以通过读取文件内容获取对应的条目值。
创建文件my-nginx-config.conf
server{
listen: 80;
server_name: www.kubia-example.com;
gzip on;
gzip_types text/plain application/xml;
location /{
root /usr/share/nginx/html;
index index.html index.htm;
}
}
创建文件sleep-interval文件,里面写入值25
创建名为fortune-config的configmap:
kubectl create configmap fortune-config --from-file=configmap-files
查看创建的configmap:kubectl get configmap fortune-config -o yaml
apiVersion: v1
data:
my-nginx-config.conf: |
server{
listen: 80;
server_name: www.kubia-example.com;
gzip on;
gzip_types text/plain application/xml;
location {
root /usr/share/nginx/html;
index index.html index.htm;
}
}
sleep-interval: |
25
kind: ConfigMap
metadata:
creationTimestamp: "2019-11-26T02:30:07Z"
name: fortune-config
namespace: default
resourceVersion: "9384620"
selfLink: /api/v1/namespaces/default/configmaps/fortune-config
uid: a92e8cad-0ff4-11ea-80c2-00163e164b6a
可以看出:configmap包含两个条目,每个条目的键是文件名。
nginx需要读取配置文件/etc/nginx/nginx.conf,并且会将其内容嵌入到/etc/nginx/conf.d/下面所有的.conf文件中,所以可以将configmap中的my-nginx-config.conf挂载到/etc/nginx/conf.d/下面,下面将configMap作为卷挂载到容器对应目录中:vim fortune-pod-configmap-volume.yaml
apiVersion: v1
kind: Pod
metadata:
name: fortune-config-volume
spec:
containers:
- image: nginx
name: web-server
volumeMounts:
- name: conf #引用下面名称为conf的volume
mountPath: /etc/nginx/conf.d #挂载到容器的该目录下
readOnly: true
volumes:
- name: conf
configMap:
name: fortune-config #名称为fortune-config的configmap
这种形式会将fortune-config下的两个文件都包含进来,如果只需要configmap中的部分文件,使用item指定。这样/etc/nginx/conf.d下面只会包含gzip.conf文件
volumes:
- name: config
configMap:
name: fortune-config
items:
- key: my-nginx-config.conf #仅使用fortune-config这个configmap中的这个key
path: gzip.conf #将上面的key指定的item存储在这里
注意:将卷挂载至某个文件夹下,文件夹下原本存在的任何文件都会被隐藏起来。如果不想原来的文件被隐藏,使用volumeMounts下的subPath属性,用来指定条目而非完整的卷。
spec:
containers:
- image: some/image
volumeMounts:
- name: myvolume
mountPath: /etc/someconfig.conf
subPath: myconfig.conf
但是这种挂载方式会有更新上的缺陷。
(5)configmap挂载到volume中的文件权限默认是644,可以修改权限:
volumes:
- name: config
configMap:
name: fortune-config
defaultMode: "6600"
66.secret
secret用法与configmap类似,secret只会写到需要访问secret节点的内存里,不会写磁盘。
etcd中会以加密方式存储secret,提高了系统的安全性。
默认情况下每个容器的/var/run/secrets/kubernetes.io/serviceaccount/下都会挂载三个secret文件:ca.crt;namespace;token
secret的data字段会被Base64编码,这样对于二进制文件也可以编程base64编码来存储,但不能大于1M。如果secret数据不想被编码可以将data变成stringData,stringData是只写的,如:
kind: Secret
apiVersion: v1
stringData:
foo: plain text
data:
https.cert: base64code
https.key: base64code
67.挂载secret到pod里:
apiVersion: v1
kind: Pod
metadata:
name: fortune-https
spec:
containers:
- image: luksa/fortune:env
name: html-generator
env:
- name: INTERVAL
valueFrom:
configMapKeyRef:
name: fortune-config
key: sleep-interval
valumeMounts:
- name: html
mountPath: /var/htdocs
- image: nginx:alpine
name: web-server
volumeMounts:
- name: html
mountPath: /usr/share/nginx/html
readOnly: true
- name: config
mountPath: /etc/nginx/conf.d
readOnly: true
- name: certs
mountPath: /etc/nginx/certs/ #配置nginx从/etc/nginx/certs中读取证书和密钥文件,将secret挂载在这里
readOnly: true
ports:
- containerPort: 80
- containerPort: 443
volumes:
- name: html
emptyDir: {}
- name: config
configMap:
name: fortune-config
items:
- key: my-nginx-config.conf
path: https.conf
- name: certs
secret:
secretName: fortune-https
68.通过环境变量的方式使用secret
env:
- name: FOO_SECRET
valueFrom:
secretKeyRef: #这里非configmap的configMapKeyRef
name: fortune-https
key: foo
但是通过环境变量的方式会暴漏出secret,所以最好使用卷的方式。
69.downwardApi
downwardApi通过环境变量或者dwonwardapi卷来对外暴露pod元数据信息。
70.downwardApi可以获取的信息:
pod名称,pod ip,pod 名称空间,pod节点名称,容器的cpu和内存使用量及限制,pod的标签,pod的注解。服务账户(pod访问api时的身份);这些大部分都能通过环境变量或者downwardapi卷暴漏,标签和注解只能通过卷暴露。
71.通过环境变量的方式传递到容器中
apiVersion: v1
kind: Pod
metadata:
name:downward
spec:
containers:
- name: main
image: busybox
command: ["sleep","999999"]
resources:
requests:
cpu: 15m
memory: 100Ki
limits:
cpu: 100m
memory: 4Mi
env:
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: POD_IP
valueFrom:
fieldRef:
fieldPath: status.podIP
- name: NODE_NAME
valueFrom:
fieldRef:
fieldPath: spec.nodeName
- name: SERVICE_ACCOUNT
valueFrom:
fieldRef:
fieldPath: spec.serviceAccountName
- name: CONTAINER_CPU_REQUEST_MILLICORES
valueFrom:
resourceFieldRef:
resource: request.cpu
divisor: 1m
- name: CONTAINER_MEMORY_LIMIT_KIBIBYTES
valueFrom:
resourceFieldRef:
resource: limits.memory
divisor: 1Ki
创建完成后,可以使用kubectl exec downward env查看到所有的环境变量。
72.通过downwardapi卷读取元数据
apiVersion: v1
kind: Pod
metadata:
name: downward
lables:
foo: bar
annotations:
key1: value1
key2: |
multi
line
value
spec:
containers:
- name: main
imgae: busybox
command: ["sleep","999999"]
resources:
requests:
cpu: 15m
memory: 100Ki
limits:
cpu: 100m
memory: 4Mi
volumeMounts:
- name: downward
downwardAPI:
items:
- path: "podName"
fieldRef:
fieldPath: metadata.name
- path: "podNamespace"
fieldRef:
fieldPath: metadata.namespace
- path: "containerCpuRequestMilliCores"
resourceFieldRef:
containerName: main
resource: requests.cpu
divisor: 1m
这里通过挂载一个名为downward的卷来挂载到/etc/downward目录下,上面定于的每个path都会对应/etc/downward下的一个文件。