docker/k8s

141 阅读8分钟

1. 命令集

1.1. docker相关

1.1.1.  查看所用容器状态 docker ps -a

1.1.2. 删除所有不再使用的容器   docker container prune

1.1.3.  build镜像 docker build -t kubia . # 当前目录下寻找dockerfile并构建镜像

1.1.4. 进入容器内部 docker exec -it <ContainerName/ContainerID> bash  # 这里-i 确保输入流开放.可以在shell中输入命令,-t分配一个伪终端.

1.1.5. 停止一个容器 docker stop <ContainerName/ContainerID> 

1.1.6. 删除一个容器 docker rm <ContainerName/ContainerID>

1.1.7. 给一个镜像添加标签 docker tag

1.1.8. 运行一个镜像 docker run -p : -d # 后台运行镜像并把容器内的IPA端口暴露在宿主机的IPB端口

1.1.9. 当自己执行docker命令没有权限,newgrp docker

1.1.10. 给镜像打tag docker tag <原镜像名> <tag名>

1.1.11. 多线程save镜像 docker save :latest | pigz --best -p 32  > .tar.gz

1.2. K8S相关

1.2.1. 获取pod信息 k get pod

1.2.2. 删除一个ReplicationControllers以及他的pods k delete replicationcontroller

1.2.3. 强行删除所有pod  k delete cm,deploy,svc,sts --all

1.2.4. 查看一个pod当前用的yaml k get pod -o yaml

1.2.5. k8s运行一个镜像,镜像内的应用监听PORT端口,最后指的是生成一个RC k run --image= --port= --generator=run/vl

1.2.6.  kubectl 的 config地址: /etc/kubernetes/kubelet.conf

1.2.7. 调整一个ns的资源限制 kubectl edit resourcequota

1.2.8. 删除所有被驱逐的节点 kubectl get pods | grep Evicted | awk '{print $1}' | xargs kubectl delete pod

1.2.9. 开端口

# 打开hostnetwork,并添加一个tcp转发规则,将9000端口(任意一个集群内节点的外网ip)转发到default空间下的nginx-service:80上,根据需求改为实际值
helm upgrade --``set controller.hostNetwork=``true``,tcp.9000=default``/nginx-service``:80 ingress stable``/nginx-ingress
# 重启所有nginx-ingress pod
kubectl -n ingress get pod | ``awk '{print $1}'``|``grep ingress| ``xargs kubectl -n ingress delete pod

\

2. docker相关

2.1. 为什么要容器? 

在同一机器上运行的不同组件可能会遇到各种问题,比如需要不同的库依赖,或者其他不同的环境需求.

当一个产品所需组件少的时候,可以通过给每个组件提供一个单独的操作系统来隔离他们的环境.

但是当组件变小而且总数变多时,这种方法就会造成很多资源浪费.这时候我们就需要用容器技术,容器允许在同一台机器上运行多个服务,不仅提供不同的环境给每个服务,而且将他们隔离.容器类似虚拟机,但是开销小很多.

容器中运行的进程实际上运行在宿主机的操作系统上.但是容器内的进程是和其他进程隔离的.

首先虚拟机需要运行自己的一组系统进程,这消耗了很多额外的计算资源.一个容器仅仅是宿主机上被隔离的单个进程,不会有其他进程的开销.

\

2.2. docker与宿主机的关系

docker内的进程实际上是跑在宿主机上的,可以再宿主机上通过ps -a获取到.但是容器内部会有一套独立的PID分配,完全独立于宿主机的进程树.

容器内部的文件系统,进程,用户,主机名,网络接口都是独立的.

让每个进程运行于自己的容器中,这是docker和k8s所期望的方式.

一个pod中的容器共享相同的IP地址和端口空间.

\

3. K8S相关

3.1. 开发者角度

开发者能指定一些容器必须一起运行,k8s将会在一个工作节点上部署他们.

开发者不应该过度考虑服务发现,扩容,负载均衡,自恢复,甚至领导者的选举.

k8s最小单位是pod,而不是容器.不能单独扩缩容器,只能单独扩缩pod

3.2. k8s集群架构

\

控制面板(master)

工作节点

API服务器

etcd

Scheduler

Controller
Manager

Kubelet

kube-proxy

容器运行时

3.3. k8s运行镜像幕后发生的事情

当运行kubectl命令时,它通过向Kubernetes API服务器发送一个REST HTTP请求,在集群中创建一个新的RC对象.然后,RC创建了一个新的pod,

调度器将其调度到一个工作节点上.kubectl看到pod被调度到节点上,就告知Docker从镜像中心拉取指定的镜像,如果本地没有镜像,则会从远端拉取,

最后Docker拉去镜像并创建运行容器.

3.4. ReplicationController角色

通常,ReplicationController(以下简称RC)用于复制pod,并让他们保持运行.如果你的pod因为任何原因消失了,那么RC将创建一个新的pod来替换消失的pod.

3.5. 为什么需要服务

pod的存在是短暂的,是有可能在任何时候消失的,当发生特殊情况pod消失的时候,RC将拉起pod,新的pod与之前的pod具有不同的IP地址,这就是需要服务的地方,解决不断变化的IP地址的问题,以及在一个固定IP和端口上对外暴露多个pod.

当一个服务被创建时,他会得到一个静态的IP,在服务的生命周期中这个IP不会发生改变.客户端应该通过固定IP地址连接到服务,而不是直接连接pod.服务会确保其中一个pod接收链接,而不关心pod运行在哪里以及他的IP是什么.

服务表示一组或多组提供相同服务的pod的静态地址.

3.6. 关于namespace

默认情况下我们所在的namespace都是default,所起的资源也都在默认的namespace下,naespace能使我们将不属于一组的资源分到不重叠的组中.

如果有多个用户或者用户组正在使用同一个集群,他们就应该使用各自的命名空间.命名空间为资源名称提供了一个作用域.除了隔离资源,namespace可用于

仅允许某些用户访问某些特定资源,还可以限制单个用户可用的计算资源数量.

3.7. 关于dns解析

首先k8s 有一个组件叫coredns,这个组件提供整个集群做内部域名解析的服务.

在k8s中,比如服务a访问服务b,对于同一个namespace下的服务,可以直接在pod中curl b来访问,对于跨namespace的情况,服务名后面对应上namespace即可.

比如我们想访问 default命名空间下的mysql服务, 那么可以通过  curl mysql.default来访问.

首先dns解析依赖容器内的resolv文件:

nameserver 10.96.0.10``search default.svc.cluster.local svc.cluster.local cluster.local yitu-inc.intra``options ndots``:``5

这里会对dns server进行配置,而且还有一些可选配置项,

nameserver:  填写dns server的IP,这里填写k8s coredns的虚拟ip就可以.

search: 代表dns解析的search域.

ndots: 如果查询的域名包含的点“.”,不到5个,那么进行DNS查找,将使用非完全限定名称(或者叫绝对域名),如果你查询的域名包含点数大于等于5,那么DNS查询,默认会使用绝对域名进行查询。(感兴趣的可以去学习一下,也可以用这个来减少dns解析浪费.)

当 我们执行一次 curl mysql 时,经过了哪些步骤呢?

首先一定要有一个service的名称为b,这是前提.

之后在容器内会根据 /etc/resolve.conf文件进行解析流程,

首先选择10.96.0.10 进行解析,然后用字符串"mysql"依次带入 search域进行dns查询.

依次执行:

if ( ``find mysql.default.svc.cluster.``local )``    ``解析完成``else if (``find mysql.svc.cluster.``local``)``    ``解析完成``else if (``find mysql.cluster.``local``)``    ``解析完成``else if (``find mysql.yitu-inc.intra)``    ``解析完成``else``    ``解析失败

这也就解释了为什么用mysql或者mysql.default都可以解析成功,但是很显然用mysql进行dns查询效率更高,因为用mysql.default会多进行一次dns解析.

在做域名解析的过程中,会同时发送A记录解析的包和AAAA记录解析的包给dns server,k8s会分配一个dns实例 进行dns解析,解析之后会返回一个包给client端,解析结束

4. 各种资源的yml写法

4.1. pod.yml 的 写法 

apiVersion: v1  ``#Kubernetes API 版本``kind: Pod ``#K8s 对象/资源 类型``metadata: # pod 元数据(名称,标签,注解等)``  ``annotations:``  ``creationTimestamp:``  ``labels:``    ``run: kubia ``# 标签在opod中经常使用``spec: # pod 规格/内容 (pod的容器列表,volume等)``  ``containers:``  ``- image``: # 容器所用的镜像``    ``imagePullPolicy: # 拉镜像的原则,默认的镜像拉取策略是 IfNotPresent,也就是不存在的时候去hub拉取,但是可以手动改成always,这样就可以每次都从远端拉镜像.  ``    ``name: #容器名``    ``ports:``    ``- containerPort``: 8080 ``#应用监听的端口``      ``protocol: TCP``    ``resources:``      ``requests:``        ``cpu: 100m``status: # pod及其内部容的详细状态

\

pod定义的主要部分

metadata: 名称、命名空间、标签

spec: pod的容器,卷和其他数据

statu: 运行中pod的当前信息,每个容器的描述和状态

5. FAQ

\

5.1. docker需要权限 

newgrp docker

5.2. 如何安装minikube

k8smeetup.github.io/docs/tasks/…

(1) 安装VirtualBox 

(2) 安装kubectl

(3) 安装minikube

(4) minikube start

过程中可能需要一些google.

5.3. 如何构建并使用本地仓库

(1) 使用registry搭建本地仓库

docker pull registry``docker run -d   -p 5000:5000   --restart=always   --name registry   -``v /mnt/docker_imgs``:``/var/lib/registry   registry


(2) docker ps 查看registry容器是否在运行

(3) 给要push的镜像打上tag 

docker tag <imageName> <localhost:5000``/imageName``>

(4) push镜像

docker push <localhost:5000``/imageName``>

(5) pull镜像

docker pull <localhost:5000``/imageName``>

5.4. 执行kubectl出现 bash: /usr/local/bin/kubectl: cannot execute binary file: Exec format error

大概率是kubectl下载成mac系统的了,下载linux重装即可.

5.5. kubectl permission denied

(1) sudo chmod +x /usr/local/bin/kubectl

(2) 把自己加入root用户组

5.6. kubectl get pod 报错 (Error from server (NotAcceptable): unknown (get nodes))

(1) 原因是server端和client端的kubectl版本不匹配.

(2) 首先kubectl version 获取server版本和client版本.

(3) 把下面的v1.8.7替换为对应的server版本即可.

$ curl -LO https:``//storage``.googleapis.com``/kubernetes-release/release/v1``.8.7``/bin/linux/amd64/kubectl``$ ``chmod +x .``/kubectl``$ ``sudo mv .``/kubectl /usr/local/bin/kubectl

5.7. dockerfile中CP出现报错

首先源文件需要在dockerfile目录中,其次不能是软链接.

5.8. 如何在pod内gdb调试

www.jianshu.com/p/967b2f37d…

\

5.9. k8s学习文档

feisky.gitbooks.io/kubernetes/…