如果您对weblogic部署——从docker到kubernetes和dockerweblogic使用感兴趣,那么这篇文章一定是您不可错过的。我们将详细讲解weblogic部署——从docker到ku
如果您对weblogic 部署 —— 从 docker 到 kubernetes和docker weblogic使用感兴趣,那么这篇文章一定是您不可错过的。我们将详细讲解weblogic 部署 —— 从 docker 到 kubernetes的各种细节,并对docker weblogic使用进行深入的分析,此外还有关于docker for mac 安装 kubernetes、kubernetes dashboard、docker kubernetes Swarm 容器编排 k8s CICD 部署 麦兜、Docker Kubernetes--services(微服务)、docker – Kubectl:Kubernetes与minikube超时的实用技巧。
本文目录一览:- weblogic 部署 —— 从 docker 到 kubernetes(docker weblogic使用)
- docker for mac 安装 kubernetes、kubernetes dashboard
- docker kubernetes Swarm 容器编排 k8s CICD 部署 麦兜
- Docker Kubernetes--services(微服务)
- docker – Kubectl:Kubernetes与minikube超时
weblogic 部署 —— 从 docker 到 kubernetes(docker weblogic使用)
这是一个证实可用的 weblogic 中间件的容器化流程。我们可以通过一键部署 WLS 从而直接利用在容器中运行的 domain 来部署应用,省去了对 WLS 本身的环境搭建,安装部署等环节;另外还可以集成 Weblogic-Kubernetes-Operator 来对 domain 进行日志收集分析、自动扩容、负载均衡等功能。
-
首先是 Weblogic 的 Docker 部署。
请仔细阅读:https://my.oschina.net/u/3867634/blog/2246865
至此,我们已经构建了 oracle/weblogic:12.2.1.3-developer 镜像,为了方便后续使用,我们可以搭建 Harbor 本地私有镜像仓库,将次镜像 push 至仓库中。
-
搭建 Harbor 仓库
请参阅:https://github.com/goharbor/harbor/blob/release-1.6.0/docs/installation_guide.md
中文版:https://blog.csdn.net/aixiaoyang168/article/details/73549898
搭建完成后,kubernetes 节点中需要修改 insecure-registry:
//编辑配置docker-option配置文件
vi /etc/systemd/system/docker.service.d/docker-options.conf
//在文件中添加 --insecure-registry=172.17.20.25
[Service]
Environment="DOCKER_OPTS=--insecure-registry=10.233.0.0/18 --insecure-registry=172.17.20.25 --graph=/var/lib/docker --log-opt max-size=50m --log-opt max-file=5 \
--iptables=false"
//重启docker
systemctl daemon-reload
systemctl restart docker
然后,将构建好的镜像 push 至仓库中:
//给image打标签
docker tag oracle/weblogic:12.1.3-developer 172.17.20.25/oracle/weblogic:12.1.3-developer
//push至172.17.20.25
docker push 172.17.20.25/oracle/weblogic:12.1.3-developer
现在,可以登录至 http://172.17.20.25 查看镜像
拉取镜像:
docker pull 172.17.20.25/oracle/weblogic:12.2.1.3-developer
-
kubernetes 集群中部署 Weblogic
拉取 docker-images 代码:
$ git clone https://github.com/oracle/docker-images.git
//进入wls-k8s-domain目录
[root@localhost ~]# cd docker-images/OracleWebLogic/samples/wls-k8s-domain/
[root@localhost wls-k8s-domain]# ls
build.sh container-scripts Dockerfile k8s README.md
构建 wls-k8s-domain 镜像:
$ docker build -t wls-k8s-domain .
将镜像 tag 打成 172.17.20.25/oracle/wls-k8s-domain:1.0 后 push 至 Harbor 以方便 k8s 节点拉取。
再修改 k8s/wls-admin.yml 为如下所示:
apiVersion: apps/v1beta1
kind: Deployment
metadata:
name: admin-server
spec:
selector:
matchLabels:
app: admin-server
replicas: 1
template:
metadata:
labels:
app: admin-server
spec:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- admin-server
topologyKey: "kubernetes.io/hostname"
containers:
- name: admin-server
#image修改为harbor上的名字
image: 172.17.20.25/oracle/wls-k8s-domain:1.0
imagePullPolicy: IfNotPresent
command: ["sh"]
args: ["/u01/oracle/startadmin.sh"]
readinessProbe:
httpGet:
path: /weblogic/ready
port: 8001
initialDelaySeconds: 15
timeoutSeconds: 5
ports:
- containerPort: 8001
env:
- name: WLUSER
valueFrom:
secretKeyRef:
name: wlsecret
key: username
- name: WLPASSWORD
valueFrom:
secretKeyRef:
name: wlsecret
key: password
volumeMounts:
- mountPath: /u01/wlsdomain
name: domain-home
volumes:
- name: domain-home
persistentVolumeClaim:
claimName: wlserver-pvc-1
---
apiVersion: v1
kind: Service
metadata:
name: admin-server
labels:
app: admin-server
spec:
type: NodePort
selector:
app: admin-server
ports:
- name: client
protocol: TCP
port: 8001
targetPort: 8001
nodePort: 30007
selector:
app: admin-server
修改 k8s/wls-stateful.yml 为:
apiVersion: apps/v1beta1 # for versions before 1.6.0 use extensions/v1beta1
kind: StatefulSet
metadata:
name: managed-server
spec:
serviceName: wls-subdomain
selector:
matchLabels:
app: managed-server
replicas: 2
template:
metadata:
name: ms
labels:
app: managed-server
spec:
#将managed-server与admin-server部署在同一个node上
affinity:
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- admin-server
topologyKey: "kubernetes.io/hostname"
subdomain: wls-subdomain
containers:
- name: managed-server
image: 172.17.20.25/oracle/wls-k8s-domain:1.0
imagePullPolicy: IfNotPresent
command: ["sh"]
args: ["/u01/oracle/startms.sh"]
readinessProbe:
httpGet:
path: /weblogic/ready
port: 8011
initialDelaySeconds: 15
timeoutSeconds: 5
ports:
- containerPort: 8011
env:
- name: JAVA_OPTIONS
value: "-Dweblogic.StdoutDebugEnabled=true"
- name: USER_MEM_ARGS
value: "-Xms64m -Xmx256m "
- name: MY_POD_IP
valueFrom:
fieldRef:
fieldPath: status.podIP
- name: MY_POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: DNS_DOMAIN_NAME
value: "wls-subdomain"
- name: WLUSER
valueFrom:
secretKeyRef:
name: wlsecret
key: username
- name: WLPASSWORD
valueFrom:
secretKeyRef:
name: wlsecret
key: password
volumeMounts:
- mountPath: /u01/wlsdomain
name: domain-home
- mountPath: /u01/filestores
name: filestore-data
volumes:
- name: domain-home
persistentVolumeClaim:
claimName: wlserver-pvc-1
- name: filestore-data
persistentVolumeClaim:
claimName: wlserver-pvc-2
---
apiVersion: v1 # headless service required for statefulSet
kind: Service
metadata:
name: wls-subdomain
labels:
app: managed-server
spec:
ports:
- name: client
port: 8011
protocol: TCP
targetPort: 8011
clusterIP: None
selector:
app: managed-server
---
apiVersion: v1
kind: Service
metadata:
name: wls-service
labels:
app: managed-server
spec:
type: NodePort
ports:
- name: client
port: 8011
protocol: TCP
targetPort: 8011
nodePort: 30009
selector:
app: managed-server
修改 k8s/pv.yml
kind: PersistentVolume
apiVersion: v1
metadata:
name: pv1
labels:
app: wls-domain
spec:
storageClassName: manual
capacity:
storage: 10Gi
accessModes:
- ReadWriteMany
persistentVolumeReclaimPolicy: Recycle # Retain, Recycle, Delete
hostPath:
#path填上本地目录
path: "/home/oracle/pv/pv1"
#nfs:
#server: <nfs_server_ip>
#path: <shared_path>
---
kind: PersistentVolume
apiVersion: v1
metadata:
name: pv2
labels:
app: wls-domain
spec:
storageClassName: manual
capacity:
storage: 10Gi
accessModes:
- ReadWriteMany
persistentVolumeReclaimPolicy: Recycle # Retain, Recycle, Delete
hostPath:
path: "/home/oracle/pv/pv2"
#nfs:
#server: <nfs_server_ip>
#path: <shared_path>
---
kind: PersistentVolume
apiVersion: v1
metadata:
name: pv3
labels:
app: wls-domain
spec:
storageClassName: manual
capacity:
storage: 10Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Recycle # Retain, Recycle, Delete
hostPath:
path: "/home/oracle/pv/pv3"
#nfs:
#server: <nfs_server_ip>
#path: <shared_path>
NOTE:hostPath 下所填的目录需有 777 权限。
IMPORTANT:在执行创建脚本之前,必须确保有一个用户的 UID 和 GID 为 1000:1000。
然后,依次执行以下命令:
$ kubectl create -f k8s/secrets.yml
$ kubectl create -f k8s/pv.yml
$ kubectl create -f k8s/pvc.yml
$ kubectl create -f k8s/wls-admin.yml
$ kubectl create -f k8s/wls-stateful.yml
至此,一个带有两个 managed-server 的 domain 便创建好了。
$ kubectl get all
NAME READY STATUS RESTARTS AGE
po/admin-server-1238998015-f932w 1/1 Running 0 11m
po/managed-server-0 1/1 Running 0 11m
po/managed-server-1 1/1 Running 0 8m
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
svc/admin-server 10.102.160.123 <nodes> 8001:30007/TCP 11m
svc/kubernetes 10.96.0.1 <none> 443/TCP 39d
svc/wls-service 10.96.37.152 <nodes> 8011:30009/TCP 11m
svc/wls-subdomain None <none> 8011/TCP 11m
NAME DESIRED CURRENT AGE
statefulsets/managed-server 2 2 11m
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
deploy/admin-server 1 1 1 1 11m
NAME DESIRED CURRENT READY AGE
rs/admin-server-1238998015 1 1 1 11m
现在可以登录 http:IP:30007/console 访问控制台,默认账号为:weblogic,密码为:weblogic1。
在 weblogic 中部署的应用访问端口为 30009。
-
改进
我们可以制作 chart 来一键安装,步骤如下:
1. 创建名为 hello-world 的 charts
helm create weblogic
2. 将 k8s / 目录放入 weblogic/templates 目录下
注:helloworld 程序简单,程序不需引入相关依赖,也不需要传入参数。charts 提供了版本控制,引入依赖,传参等配置文件。
3. 打包 tar
helm package weblogic
4. 在本地创建 charts 文件夹,并将打包的 tar 文件移入,生成 index.yaml
mv weblogic-0.1.0.tgz charts/
helm serve --repo-path ./charts
5、安装 chart
helm install weblogic
docker for mac 安装 kubernetes、kubernetes dashboard
-
安装参考地址(按照此文档,安装成功):https://yq.aliyun.com/articles/508460
-
官方说明:https://kubernetes.io/docs/tasks/access-application-cluster/web-ui-dashboard/
-
常用命令 kubectl 命令:
kubectl get namespaces
kubectl get pods --namespace kube-system
kubectl get deployments --namespace kube-system
kubectl get services --namespace kube-system
kubectl -n kube-system edit service kubernetes-dashboard
kubectl get pods
kubectl get deployments
kubectl get services
kubectl config view
获取令牌,然后登陆 kubernetes dashboard
➜ ~ kubectl get secrets
NAME TYPE DATA AGE
default-token-6ljm8 kubernetes.io/service-account-token 3 6h
➜ ~ kubectl describe secrets default-token-6ljm8
Name: default-token-6ljm8
Namespace: default
Labels: <none>
Annotations: kubernetes.io/service-account.name=default
kubernetes.io/service-account.uid=77d014c2-0804-11e9-acd8-025000000001
Type: kubernetes.io/service-account-token
Data
====
ca.crt: 1025 bytes
namespace: 7 bytes
token: eyJhbGciOiJSUzI1NiIsImtpZCI6IiJ9.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJkZWZhdWx0Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZWNyZXQubmFtZSI6ImRlZmF1bHQtdG9rZW4tNmxqbTgiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC5uYW1lIjoiZGVmYXVsdCIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50LnVpZCI6Ijc3ZDAxNGMyLTA4MDQtMTFlOS1hY2Q4LTAyNTAwMDAwMDAwMSIsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDpkZWZhdWx0OmRlZmF1bHQifQ.G9TGa4KGj5B-cMv-0-vuangR2_tFiQ1nJMgtsEPs1BEwPAyjmaC-BL5y0Ux9HyC1mlt0DklO-8_o41i4OD_w0wLymxi8zZQxgY7Tlu3_oE5OKnK58xWN-mMTKKnvfDpZrIBbkWQ5EB49LC7QiTBKGAoixGyOBvU1fmD2AzpdO3sWvNsaOWbMLFcwzHA-M2V-CKU3I07Hxs6uIi9juk4IqkTryfvCDUafTrubpkVktwQr7UwzvmKfbPoWLyn1tbCDhR3Il64daoTE9nlmqWwYZZFmfaZjWWWYfi3QPXuNUNpXRVVd_6gcjUzebR1o-22KoOUbobQ94K-1bYJOQSZNnA
将 token 部分复制到登录页的 token 输入框,登陆即可。 出处:http://www.cnblogs.com/along21/p/9811860.html#auto_id_11
docker kubernetes Swarm 容器编排 k8s CICD 部署 麦兜
1docker 版本
docker 17.09
https://docs.docker.com/
appledeAir:~ apple$ docker version
Client: Docker Engine - Community
Version: 18.09.0
API version: 1.39
Go version: go1.10.4
Git commit: 4d60db4
Built: Wed Nov 7 00:47:43 2018
OS/Arch: darwin/amd64
Experimental: false
Server: Docker Engine - Community
Engine:
Version: 18.09.0
API version: 1.39 (minimum version 1.12)
Go version: go1.10.4
Git commit: 4d60db4
Built: Wed Nov 7 00:55:00 2018
OS/Arch: linux/amd64
Experimental: false
vagrant
创建 linux 虚拟机
创建一个目录
mkdir centos7
vagrant init centos/7 #会创建一个 vagrant file
vagrant up # 启动
vagrant ssh # 进入虚拟机
vagrant status
vagrant halt # 停机
vagrant destroy 删除机器
docker machine 自动在虚拟机安装 docker 的工具
docker-machine create demo virtualbox 里会自动运行一台虚拟机
docker-machine ls 显示有哪些虚拟机在运行
docker-machine ssh demo 进入机器
docker-machine create demo1 创建第二台有 docker 的虚拟机
docker-machine stop demo1
docker playground https://labs.play-with-docker.com/
运行 docker
docker run -dit ubuntu /bin/bash
执行不退出
docker exec -it 33 /bin/bash
把普通用户添加到 docker 组,不用 sudo
sudo gpasswd -a alex docker
/etc/init.d/docker restart
重新登录 shell exit
验证 docker version
创建自己的 image
from scratch
ADD app.py /
CMD ["/app.py"]
build 自己的 image
docker build -t alex/helloworld .
显示当前正在运行的容器
docker container ls
docker container ls -a
显示状态为退出的容器
docker container ls -f "status=exited" -q
删除容器
docker container rm 89123
docker rm 89123
或者一次性删除全部容器
docker rm $(docker container ls -aq)
删除退出状态的容器
docker rm $(docker container ls -f "status=exited" -q)
删除不用的 image
docker rmi 98766
把 container,commit 成为一个新的 image
docker commit 12312312 alexhe/changed_a_lot:v1.0
docker image ls
docker history 901923123 (image 的 id)
Dockerfile 案例:
cat Dockerfile
FROM centos
ENV name Docker
CMD echo "hello $name"
用 dockerfile 建立 image
docker build -t alexhe/firstblood:latest .
从 registry 拉取
docker pull ubuntu:18.04
Dockerfile 案例:
cat Dockerfile
FROM centos
RUN yum install -y vim
Dockerfile 案例:
FROM ubuntu
RUN apt-get update && apt-get install -y python
Dockerfile 语法梳理及最佳实践
From ubuntu:18.04
LABEL maintainer="alex@alexhe.net"
LABEL version="1.0"
LABEL description="This is comment"
RUN yum update && yum instlal -y vim \
python-dev # 每运行一次 run,增加一层 layer,需要合并起来
WORKDIR /root # 进入目录,如果没有目录会自动创建目录
WORKDIR demo #进入了 /root/demo
ADD hello /
ADD test.tar.gz/ # 添加到根目录并解压
WORKDIR /root
ADD hello test/ # /root/test/hello
WORKDIR /root
COPY hello test/ #
大部分情况,copy 优于 add,add 除了 copy 还有额外功能(解压),添加远程文件 / 目录请使用 curl 或者 wget
ENV MYSQL_VERSION 5.6 # 设置常亮
RUN apt-get install -y mysql-server="${MYSQL_VERSION}" && rm -rf /var/lib/apt/lists/* #引用常量
RUN vs CMD vs ENTRYPOINT
run: 执行命令并创建新的 image layer
cmd:设置容器启动后默认执行的命令和参数
entrypoint: 设置容器启动时运行的命令
shell 格式
RUN apt-get install -y vim
CMD echo "hello docker"
ENTRYPOINT echo "hello docker"
Exec 格式
RUN ["apt-get","install","-y","vim"]
CMD ["/bin/echo","hello docker"]
ENTRYPOINT ["/bin/echo","hello docker"]
例子:注意
FROM centos
ENV name Docker
ENTRYPOINT ["/bin/bash","-c","echo","hello $name"] #这样正解 如果 ["echo","hello $name"],这样运行了以后还是显示 hello $name,没有变量替换。用 exec 格式,执行的是 echo 这个命令,而不是 shell,所以没办法把变量替换掉。
和上面的区别
FROM centos
ENV name Docker
ENTRYPOINT echo "hello $name" # 正常 可以显示 hello Docker 会用 shell 执行命令,识别变量
CMD:
容器启动时默认执行的命令,如果 docker run 指定了其他命令,CMD 命令被忽略。如果定义了多个 CMD,只有最后一个会执行。
ENTRYPOINT:
让容器以应用程序或者服务的形式运行。不会被忽略,一定会执行。最佳实践:下一个 shell 脚本作为 entrypoint
COPY docker-entrypoint.sh /usr/local/bin/
ENTRYPOINT ["docker-entrypoint.sh"]
EXPOSE 27017
CMD ["mongod"]
镜像发布
docker login
docker push alexhe/hello-world:latest
docker rmi alexhe/hello-world # 删掉
docker pull alexhe/hello-world:latest # 再拉回来
本地 registry private repository
https://docs.docker.com/v17.09/registry/
1. 启动私有 registry
docker run -d -p 5000:5000 -v /opt/registry:/var/lib/registry --restart always --name registry registry:2
2. 其他机器测试 telnet x.x.x.x 5000
3. 往私有 registry push
3.1 先用 dockerfile build 和打 tag
docker build -t x.x.x.x:5000/hello-world .
3.2 设置允许不安全的私有库
vim /etc/docker/daemon.json
{
"insecure-registries" : ["x.x.x.x:5000"] }
vim /lib/systemd/service/docker.service
EnvirmentFile=/etc/docker/daemon.json
/etc/init.d/docker restart
3.3 开始 push
docker push x.x.x.x:5000/hello-world
3.4 验证
registry 有 api https://docs.docker.com/v17.09/registry/spec/api/#listing-repositories
GET /v2/_catalog
docker pull x.x.x.x:5000/helloworld
Dockerfile github 很多示例 https://github.com/docker-library/docs https://docs.docker.com/engine/reference/builder/#add
Dockerfile 案例:安装 flask 复制目录中的 app.py 到 /app/ 进入 app 目录 暴露 5000 端口 执行 app.py
cat Dockerfile
FROM python:2.7
LABEL maintainer="alex he<alex@alexhe.net>"
RUN pip install flask
COPY app.py /app/
WORKDIR /app
EXPOSE 5000
CMD ["python", "app.py"]
cat app.py
from flask import Flask
app = Flask(__name__)
@app.route(''/'')
def hello():
return "hello docker"
if __name__ == ''__main__'':
app.run(host="0.0.0.0", port=5000)
docker build -t alexhe/flask-hello-world . # 打包
如果打包时出错
docker run -it 报错时的第几步 id /bin/bash
进入以后看看哪里报错
最后 docker run -d alexhe/flask-hello-world # 让容器在后台运行
在运行中的容器,执行命令:
docker exec -it xxxxxx /bin/bash
显示 ip 地址:
docker exec -it xxxx ip a
docker inspect xxxxxxid
显示容器运行产生的输出:
docker logs xxxxx
dockerfile 案例:
linux 的 stress 工具
cat Dockerfile
FROM ubuntu
RUN apt-get update && apt-get install -y stress
ENTRYPOINT ["/usr/bin/stress"] #使用 entrypoint 加 cmd 配合使用,cmd 为空的,用 docker run 来接收请求参数
CMD []
使用:
docker build alexhe/ubuntu-stress .
#dokcer run -it alexhe/ubuntu-stress # 无任何参数运行,类似于打印
docker run -it alexhe/ubuntu-stress -vm 1 --verbose # 类似于运行 stress -vm 1 --verbose
容器资源限制,cpu,ram
docker run --memory=200M alexhe/ubuntu-stress -vm 1 --vm-bytes=500M --verbose # 直接报错,内存不够。因为给了容器 200m,压力测试占用 500m
docker run --cpu-shares=10 --name=test1 alexhe/ubuntu-stress -vm1 # 和下面一起启动,他的 cpu 占用率为 66%
docker run --cpu-shares=5 --name=test2 alexhe/ubuntu-stress -vm1 # 一起启动,他的 cpu 占用率 33%
容器网络
单机:bridge,host,none
多机:Overlay
linux 中的网络命名空间
docker run -dit --name test1 busybox /bin/sh -c "while true;do sleep 3600;done"
docker exec -it xxxxx /bin/sh
ip a 显示网络接口
exit
进入 host , 执行 ip a ,显示 host 的接口
container 和 host 的网络 namespace 是隔离开的
docker run -dit --name test2 busybox /bin/sh -c "while true;do sleep 3600;done"
docker exec xxxxx ip a # 看第二台机器的网络
同一台机器,container 之间的网络是相通的。
以下是 linux 中的网络命名空间端口互通的原理实现(docker 的和他类似):
host 中执行 ip netns list 查看本机的 network namespace
ip netns delete test1
ip netns add test1 #创建 network namespace
ip netns add test2 # 创建 network namespace
在 test1 的 network namespace 中执行 ip link
ip netns exec test1 ip link # 目前状态是 down 的
ip netns exec test1 ip link set dev lo up # 状态变成了 unknown,要两端都连通,他才会变成 up
创建一对 veth,一个放入 test1 的 namespace,另一个放入 test2 的 namespace。
创建一对 veth:
ip link add veth-test1 type veth peer name veth-test2
把 veth-test1 放入 test1 的 namespace:
ip link set veth-test1 netns test1
看看 test1 的 namespace 里的情况:
ip netns exec test1 ip link #test1 的 namespace 多了一个 veth,状态为 down
看看本地的 ip link:
ip link #少了一个,说明这一个已经加到了 test1 的 namespace
把 veth-test2 放入 test2 的 namespace:
ip link set veth-test2 netns test2
看看本地的 ip link:
ip link # 又少了一个,说明已经加入到了 test2 的 namespace
看看 test2 的 namespace
ip netns exec test2 ip link #test2 的 namespace 多了一个 veth,状态为 down
给两个 veth 端口添加 ip 地址:
ip netns exec test1 ip addr add 192.168.1.1/24 dev veth-test1
ip netns exec test2 ip addr add 192.168.1.2/24 dev veth-test2
查看 test1 和 test2 的 ip link
ip netns exec test1 ip link # 发现没有 ip 地址,并且端口状态是 down
ip netns exec test2 ip link # 发现没有 ip 地址,并且端口状态是 down
把两个端口 up 起来
ip netns exec test1 ip link set dev veth-test1 up
ip netns exec test2 ip link set dev veth-test2 up
查看 test1 和 test2 的 ip link
ip netns exec test1 ip link # 发现有 ip 地址,并且端口状态是 up
ip netns exec test2 ip link # 发现有 ip 地址,并且端口状态是 up
从 test1 的 namespace 里的 veth-test1 执行 ping test2 的 namespace 中的 veth-test2
ip netns exec test1 ping 192.168.1.2
ip netns exec test2 ping 192.168.1.1
docker 的 bridge docker0 网络:
两个容器 test1 和 test2 能互相 ping 通,说明两个 network namespace 是连接在一起的。
目前系统只有一个 test1 的容器,删除 test2 容器
显示 docker 网络:
docker network ls
NETWORK ID NAME DRIVER SCOPE
9d133c1c82ff bridge bridge local
e44acf9eff90 host host local
bc660dbbb8b6 none null local
显示 bridge 网络的详情:
docker network inspect xxxxxx (上面显示 bridge 网络的 id)
host 上的 veth 和容器里的 eth0 是一对儿 veth
ip link #veth6aa1698@if18
docker exec test1 ip link #18: eth0@if19
这一对儿 veth pair 连接到了 host 上的 docker0 上面。
yum install bridge-utils
brctl show #主机上的 veth6aa 连接在 docker0 上
新开一个 test2 的容器:
docker run -dit --name test2 busybox /bin/sh -c "while true;do sleep 3600;done"
看看 docker 的网络:
docker network inspect bridge
看到 container 多了一个,地址都有
在 host 运行 ip a,又多了一个 veth。
运行 brctl show,docker0 上有两个接口
docker 容器之间的互联 link
目前只有一个容器 test1
现在创建第二个容器 test2
docker run -d --name test2 --link test1 busybox /bin/sh -c "while true;do sleep 3600;done"
docker exec -it test2 /bin/sh
进入 test2 后,去 ping test1 的 ip 地址,通,ping test1 的名字 ,也通。
进入 test1 里,去 ping test2 的 ip 地址,通,ping test2 的名字,不通。
自己建一个 docker network bridge,并让容器连接他。
docker network create -d bridge my-bridge
创建一个容器,test3
docker run -d --name test3 --network my-bridege busybox /bin/sh -c "while true;do sleep 3600;done"
通过 brctl show 来查看。
把 test2 的网络换成 my-bridge
docker network connect my-bridge test2,当连接进来后,test2 就有了 2 个 ip 地址。
注意:如果用户自己创建自定义的 network,并让一些容器连接进来,这些容器,是能通过名字来互相 ping 连接的。而默认的 bridge 不行,就像上面测试一样。
docker 的端口映射
创建一个 nginx 的 container
docker run --name web -d -p 80:80 nginx
docker 的 host 和 none 网络
none network:
docker run -d --name test1 --network none busybox /bin/sh -c "while true;do sleep 3600;done"
docker network inspect none # 可以看到 none 的 network 连接了一个 container
进入容器:
docker exec -it test1 /bin/sh # 进入看看网络,无任何 ip 网络
host network:
docker run -d --name test1 --network host busybox /bin/sh -c "while true;do sleep 3600;done"
docker network inspect host
进入容器:
docker exec -it test1 /bin/sh #查看 ip a 网络,容器的 ip 和主机的 ip 完全一样,他没有自己独立的 namespace
多容器复杂应用的部署:
Flask+redis, flask 的 container 访问 redis 的 container
cat app.py
from flask import Flask
from redis import Redis
import os
import socket
app = Flask(__name__)
redis = Redis(host=os.environ.get(''REDIS_HOST'', ''127.0.0.1''), port=6379)
@app.route(''/'')
def hello():
redis.incr(''hits'')
return ''Hello Container World! I have been seen %s times and my hostname is %s.\n'' % (redis.get(''hits''),socket.gethostname())
if __name__ == "__main__":
app.run(host="0.0.0.0", port=5000, debug=True)
cat Dockerfile
FROM python:2.7
LABEL maintaner="Peng Xiao xiaoquwl@gmail.com"
COPY . /app
WORKDIR /app
RUN pip install flask redis
EXPOSE 5000
CMD [ "python", "app.py" ]
1. 创建 redis 的 container:
docker run -d --name redis redis
2. dokcer build -t alexhe/flask-redis .
3. 创建 container
docker run -d -p 5000:5000 --link redis --name flask-redis -e REDIS_HOST=redis alexhe/flask-redis #和上面源码的相对应
4. 进入上面的 container, 并执行 env 看一下:
docker exec -it flask-redis /bin/bash
env # 环境变量
ping redis # 在容器里可以 ping redis
5. 在主机访问 curl 127.0.0.1:5000。可以访问到
多主机间,多 container 互相通信
docker 网络的 overlay 和 underlay:
两台 linux 主机 192.168.205.10 192.168.205.11
vxlan 数据包(google 搜 vxlan 概念)
cat multi-host-network.md
# Mutil-host networking with etcd
## setup etcd cluster
在docker-node1上
```
vagrant@docker-node1:~$ wget https://github.com/coreos/etcd/releases/download/v3.0.12/etcd-v3.0.12-linux-amd64.tar.gz
vagrant@docker-node1:~$ tar zxvf etcd-v3.0.12-linux-amd64.tar.gz
vagrant@docker-node1:~$ cd etcd-v3.0.12-linux-amd64
vagrant@docker-node1:~$ nohup ./etcd --name docker-node1 --initial-advertise-peer-urls http://192.168.205.10:2380 \
--listen-peer-urls http://192.168.205.10:2380 \
--listen-client-urls http://192.168.205.10:2379,http://127.0.0.1:2379 \
--advertise-client-urls http://192.168.205.10:2379 \
--initial-cluster-token etcd-cluster \
--initial-cluster docker-node1=http://192.168.205.10:2380,docker-node2=http://192.168.205.11:2380 \
--initial-cluster-state new&
```
在docker-node2上
```
vagrant@docker-node2:~$ wget https://github.com/coreos/etcd/releases/download/v3.0.12/etcd-v3.0.12-linux-amd64.tar.gz
vagrant@docker-node2:~$ tar zxvf etcd-v3.0.12-linux-amd64.tar.gz
vagrant@docker-node2:~$ cd etcd-v3.0.12-linux-amd64/
vagrant@docker-node2:~$ nohup ./etcd --name docker-node2 --initial-advertise-peer-urls http://192.168.205.11:2380 \
--listen-peer-urls http://192.168.205.11:2380 \
--listen-client-urls http://192.168.205.11:2379,http://127.0.0.1:2379 \
--advertise-client-urls http://192.168.205.11:2379 \
--initial-cluster-token etcd-cluster \
--initial-cluster docker-node1=http://192.168.205.10:2380,docker-node2=http://192.168.205.11:2380 \
--initial-cluster-state new&
```
检查cluster状态
```
vagrant@docker-node2:~/etcd-v3.0.12-linux-amd64$ ./etcdctl cluster-health
member 21eca106efe4caee is healthy: got healthy result from http://192.168.205.10:2379
member 8614974c83d1cc6d is healthy: got healthy result from http://192.168.205.11:2379
cluster is healthy
```
## 重启docker服务
在docker-node1上
```
$ sudo service docker stop
$ sudo /usr/bin/dockerd -H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock --cluster-store=etcd://192.168.205.10:2379 --cluster-advertise=192.168.205.10:2375&
```
在docker-node2上
```
$ sudo service docker stop
$ sudo /usr/bin/dockerd -H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock --cluster-store=etcd://192.168.205.11:2379 --cluster-advertise=192.168.205.11:2375&
```
## 创建overlay network
在docker-node1上创建一个demo的overlay network
```
vagrant@docker-node1:~$ sudo docker network ls
NETWORK ID NAME DRIVER SCOPE
0e7bef3f143a bridge bridge local
a5c7daf62325 host host local
3198cae88ab4 none null local
vagrant@docker-node1:~$ sudo docker network create -d overlay demo
3d430f3338a2c3496e9edeccc880f0a7affa06522b4249497ef6c4cd6571eaa9
vagrant@docker-node1:~$ sudo docker network ls
NETWORK ID NAME DRIVER SCOPE
0e7bef3f143a bridge bridge local
3d430f3338a2 demo overlay global
a5c7daf62325 host host local
3198cae88ab4 none null local
vagrant@docker-node1:~$ sudo docker network inspect demo
[
{
"Name": "demo",
"Id": "3d430f3338a2c3496e9edeccc880f0a7affa06522b4249497ef6c4cd6571eaa9",
"Scope": "global",
"Driver": "overlay",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": {},
"Config": [
{
"Subnet": "10.0.0.0/24",
"Gateway": "10.0.0.1/24"
}
]
},
"Internal": false,
"Containers": {},
"Options": {},
"Labels": {}
}
]
```
我们会看到在node2上,这个demo的overlay network会被同步创建
```
vagrant@docker-node2:~$ sudo docker network ls
NETWORK ID NAME DRIVER SCOPE
c9947d4c3669 bridge bridge local
3d430f3338a2 demo overlay global
fa5168034de1 host host local
c2ca34abec2a none null local
```
通过查看etcd的key-value, 我们获取到,这个demo的network是通过etcd从node1同步到node2的
```
vagrant@docker-node2:~/etcd-v3.0.12-linux-amd64$ ./etcdctl ls /docker
/docker/network
/docker/nodes
vagrant@docker-node2:~/etcd-v3.0.12-linux-amd64$ ./etcdctl ls /docker/nodes
/docker/nodes/192.168.205.11:2375
/docker/nodes/192.168.205.10:2375
vagrant@docker-node2:~/etcd-v3.0.12-linux-amd64$ ./etcdctl ls /docker/network/v1.0/network
/docker/network/v1.0/network/3d430f3338a2c3496e9edeccc880f0a7affa06522b4249497ef6c4cd6571eaa9
vagrant@docker-node2:~/etcd-v3.0.12-linux-amd64$ ./etcdctl get /docker/network/v1.0/network/3d430f3338a2c3496e9edeccc880f0a7affa06522b4249497ef6c4cd6571eaa9 | jq .
{
"addrSpace": "GlobalDefault",
"enableIPv6": false,
"generic": {
"com.docker.network.enable_ipv6": false,
"com.docker.network.generic": {}
},
"id": "3d430f3338a2c3496e9edeccc880f0a7affa06522b4249497ef6c4cd6571eaa9",
"inDelete": false,
"ingress": false,
"internal": false,
"ipamOptions": {},
"ipamType": "default",
"ipamV4Config": "[{\"PreferredPool\":\"\",\"SubPool\":\"\",\"Gateway\":\"\",\"AuxAddresses\":null}]",
"ipamV4Info": "[{\"IPAMData\":\"{\\\"AddressSpace\\\":\\\"GlobalDefault\\\",\\\"Gateway\\\":\\\"10.0.0.1/24\\\",\\\"Pool\\\":\\\"10.0.0.0/24\\\"}\",\"PoolID\":\"GlobalDefault/10.0.0.0/24\"}]",
"labels": {},
"name": "demo",
"networkType": "overlay",
"persist": true,
"postIPv6": false,
"scope": "global"
}
```
## 创建连接demo网络的容器
在docker-node1上
```
vagrant@docker-node1:~$ sudo docker run -d --name test1 --net demo busybox sh -c "while true; do sleep 3600; done"
Unable to find image ''busybox:latest'' locally
latest: Pulling from library/busybox
56bec22e3559: Pull complete
Digest: sha256:29f5d56d12684887bdfa50dcd29fc31eea4aaf4ad3bec43daf19026a7ce69912
Status: Downloaded newer image for busybox:latest
a95a9466331dd9305f9f3c30e7330b5a41aae64afda78f038fc9e04900fcac54
vagrant@docker-node1:~$ sudo docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a95a9466331d busybox "sh -c ''while true; d" 4 seconds ago Up 3 seconds test1
vagrant@docker-node1:~$ sudo docker exec test1 ifconfig
eth0 Link encap:Ethernet HWaddr 02:42:0A:00:00:02
inet addr:10.0.0.2 Bcast:0.0.0.0 Mask:255.255.255.0
inet6 addr: fe80::42:aff:fe00:2/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1450 Metric:1
RX packets:15 errors:0 dropped:0 overruns:0 frame:0
TX packets:8 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:1206 (1.1 KiB) TX bytes:648 (648.0 B)
eth1 Link encap:Ethernet HWaddr 02:42:AC:12:00:02
inet addr:172.18.0.2 Bcast:0.0.0.0 Mask:255.255.0.0
inet6 addr: fe80::42:acff:fe12:2/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:8 errors:0 dropped:0 overruns:0 frame:0
TX packets:8 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:648 (648.0 B) TX bytes:648 (648.0 B)
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::1/128 Scope:Host
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
vagrant@docker-node1:~$
```
在docker-node2上
```
vagrant@docker-node2:~$ sudo docker run -d --name test1 --net demo busybox sh -c "while true; do sleep 3600; done"
Unable to find image ''busybox:latest'' locally
latest: Pulling from library/busybox
56bec22e3559: Pull complete
Digest: sha256:29f5d56d12684887bdfa50dcd29fc31eea4aaf4ad3bec43daf19026a7ce69912
Status: Downloaded newer image for busybox:latest
fad6dc6538a85d3dcc958e8ed7b1ec3810feee3e454c1d3f4e53ba25429b290b
docker: Error response from daemon: service endpoint with name test1 already exists. #已经用过不能再用
vagrant@docker-node2:~$ sudo docker run -d --name test2 --net demo busybox sh -c "while true; do sleep 3600; done"
9d494a2f66a69e6b861961d0c6af2446265bec9b1d273d7e70d0e46eb2e98d20
```
验证连通性。
```
vagrant@docker-node2:~$ sudo docker exec -it test2 ifconfig
eth0 Link encap:Ethernet HWaddr 02:42:0A:00:00:03
inet addr:10.0.0.3 Bcast:0.0.0.0 Mask:255.255.255.0
inet6 addr: fe80::42:aff:fe00:3/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1450 Metric:1
RX packets:208 errors:0 dropped:0 overruns:0 frame:0
TX packets:201 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:20008 (19.5 KiB) TX bytes:19450 (18.9 KiB)
eth1 Link encap:Ethernet HWaddr 02:42:AC:12:00:02
inet addr:172.18.0.2 Bcast:0.0.0.0 Mask:255.255.0.0
inet6 addr: fe80::42:acff:fe12:2/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:8 errors:0 dropped:0 overruns:0 frame:0
TX packets:8 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:648 (648.0 B) TX bytes:648 (648.0 B)
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::1/128 Scope:Host
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
vagrant@docker-node1:~$ sudo docker exec test1 sh -c "ping 10.0.0.3"
PING 10.0.0.3 (10.0.0.3): 56 data bytes
64 bytes from 10.0.0.3: seq=0 ttl=64 time=0.579 ms
64 bytes from 10.0.0.3: seq=1 ttl=64 time=0.411 ms
64 bytes from 10.0.0.3: seq=2 ttl=64 time=0.483 ms
^C
vagrant@docker-node1:~$
```
docker 的持久化存储和数据共享:
持久化有两种方式:1,Data Volume 2,Bind Mounting
第一种 Data Volume:
容器产生数据,比如日志,数据库,想保留这些数据
例如 https://hub.docker.com/_/mysql
docker run -d -e MYSQL_ALLOW_EMPTY_PASSWORD=yes --name mysql1 mysql
查看 volume:
docker volume ls
删除 volume
docker volume rm xxxxxxxxxx
查看细节:
docker volume inspect xxxxxxxxx
创建第二个 mysql container
docker run -d -e MYSQL_ALLOW_EMPTY_PASSWORD=yes --name mysql2 mysql
查看细节:
docker volume inspect xxxxxxxxx
删除 container,volume 是不会删除的:
docker stop mysql1 mysql2
docker rm mysql1 mysql2
docker volume ls # 数据还在
重新创建 mysql1:
docker run -d -v mysq:/var/lib/mysql -e MYSQL_ALLOW_EMPTY_PASSWORD=yes --name mysql1 mysql # 这里的 mysq 是 volume 的名字
docker volume ls # 会显示 mysq
进入 mysql1 的 container
创建一个新的数据库
create database docker;
退出容器,把 mysql1 container 删除
docker rm -f mysql1 # 强制停止和删除 mysql1 这个 container
查看 volume:
docker volume ls # 还在
创建一个新的 mysql2 container,但是 volume 使用之前的 mysq
docker run -d -v mysq:/var/lib/mysql -e MYSQL_ALLOW_EMPTY_PASSWORD=yes --name mysql2 mysql
进入 mysql2 的容器里,看看数据库在不在
show database #数据库还在
第二种持久化方式:bind mounting
和第一种方式区别是什么?如果用 data volume 方式,需要在 dockerfile 里定义创建的 volume,bind mounting 不需要,bind mouting 只需要在运行时指定本地目录和容器目录一一对应的关系。
然后通过这种方式去做一个同步,就是说本地系统中的文件和容器中的文件是同步的。本地文件做了修改,容器目录中的文件也会做修改。
cat Dockerfile
# this same shows how we can extend/change an existing official image from Docker Hub
FROM nginx:latest
# highly recommend you always pin versions for anything beyond dev/learn
WORKDIR /usr/share/nginx/html
# change working directory to root of nginx webhost
# using WORKDIR is prefered to using ''RUN cd /some/path''
COPY index.html index.html
# I don''t have to specify EXPOSE or CMD because they''re in my FROM
index.html 随便整一个
docker build -t alexhe/my-nginx .
docker run -d -p 80:80 -v $(pwd):/usr/shar/nginx/html --name web alexhe/my-nginx
bind mount 其他案例:
cat Dockerfile
FROM python:2.7
LABEL maintainer="alexhe<alex@alexhe.net>"
COPY . /skeleton
WORKDIR /skeleton
RUN pip install -r requirements.txt
EXPOSE 5000
ENTRYPOINT ["scripts/dev.sh"]
开始 build image
docker build -t alexhe/flask-skeleton
docker run -d -p 80:5000 -v $(pwd):/skeleton --name flask alexhe/flask-skeleton
其他源码在
/Users/apple/temp/docker-k8s-devops-master/chapter5/labs/flask-skeleton
部署一个 WordPress:
docker run -d -v mysql-data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=root -e MYSQL_DATABASE=wordpress --name mysql mysql
docker run -d -e WORDPRESS_DB_HOST=mysql:3306 -e WORDPRESS_DB_PASSWORD=root --link mysql -p 8080:80 wordpress
docker compose:
官网介绍 https://docs.docker.com/compose/overview/
通过一个 yml 文件定义多容器的 docker 应用
通过一条命令就可以根据 yml 文件的定义去创建或者管理这多个容器
docker compose 的三大概念:Services,Networks,Volumes
v2 可以运行在单机,v3 可以运行在多机
services:一个 service 代表一个 container,这个 container 可以从 dokcerhub 的 image 来创建,或者从本地的 dockerfile build 出来的 image 来创建
service 的启动,类似 docker run,我们可以给其制定 network 和 volume,所以可以给 service 指定 network 和 volume 的引用。
例子:
services:
db: (container 的名字叫 db)
image:postgres:9.4(docker hub 拉取的)
volumes:
- "db-data:/var/lib/postgresql/data"
networks:
- back-tier
就像这样:
docker run -d --network back-tier -v db-data:/var/lib/postgresql/data postgres:9.4
例子:
services:
worker: (container 的名字)
build: ./worker (不是从 dockerhub 取,而是从本地 build)
links:
- db
- redis
networks:
- back-tier
例子:
cat docker-compose.yml
version: ''3''
services:
wordpress:
image: wordpress
ports:
- 8080:80
environment:
WORDPRESS_DB_HOST: mysql
WORDPRESS_DB_PASSWORD: root
networks:
- my-bridge
mysql:
image: mysql
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: wordpress
volumes:
- mysql-data:/var/lib/mysql
networks:
- my-bridge
volumes:
mysql-data:
networks:
my-bridge:
driver: bridge
docker-compose 的安装和基本使用:
安装:https://docs.docker.com/compose/install/
curl -L "https://github.com/docker/compose/releases/download/1.23.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose
docker-compose --version
docker-compose version 1.23.2, build 1110ad01
使用:
用上面的 docker-compose.yml
docker-compose up #在当前文件夹的 docker-compose.yml,启动. 1. 创建 bridge 网络 wordpress_my-bridge. 2. 创建 2 个 service wordpress_wordpress_1 和 wordpress_mysql_1,并且启动 container
docker-compose -f xxxx/docker-compose.yml # 在调用指定文件夹中的 docker-compose.yml
docker-compose ps # 显示目前的 service
docker-compose stop
docker-compose down #stop and remove, 但是不会删除 image
docker-compose start
docker-compose up -d # 后台执行,不显示日志
docker-compose images #显示 yml 中定义的 container 和使用的 image
docker-compose exec mysql bash #mysql 是 yml 中定义的 service,进入 mysql 这台 container 的 bash
案例:docker-compose 调用 Dockerfile 来创建
源码在 /Users/apple/temp/docker-k8s-devops-master/chapter6/labs/flask-redis
cat docker-compose.yml
version: "3"
services:
redis:
image: redis
web:
build:
context: . #dockerfile 的位置
dockerfile: Dockerfile # 调用目录中的 Dockerfile
ports:
- 8080:5000
environment:
REDIS_HOST: redis
cat Dockerfile
FROM python:2.7
LABEL maintaner="alexhe alex@alexhe.net"
COPY . /app
WORKDIR /app
RUN pip install flask redis
EXPOSE 5000
CMD [ "python", "app.py" ]
使用:docker-compose up -d #如果不使用 - d 会一直停在那里 web 信息输出在前端
docker-compose 中的 scale
docker-compose up # 用上面的 yml
docker-compose up --scale web=3 -d # 会报错,报 8080 已经被占用,需要把上面的 ports: - 8000:5000 删除
删除后再执行上面的。会启动 3 个 container,并监听了容器本地的 5000。可用 docker-compose ps 查看
但这样不行,容器本地的 5000 端口我们访问不到。我们需要在 yml 里新增 haproxy
cat docker-compose.yml
version: "3"
services:
redis:
image: redis
web:
build:
context: .
dockerfile: Dockerfile
environment:
REDIS_HOST: redis
lb:
image: dockercloud/haproxy
links:
- web
ports:
- 8080:80
volumes:
- /var/run/docker.sock:/var/run/docker.sock
cat Dockerfile
FROM python:2.7
LABEL maintaner="alex alex@alexhe.net"
COPY . /app
WORKDIR /app
RUN pip install flask redis
EXPOSE 80
CMD [ "python", "app.py" ]
cat app.py
from flask import Flask
from redis import Redis
import os
import socket
app = Flask(__name__)
redis = Redis(host=os.environ.get(''REDIS_HOST'', ''127.0.0.1''), port=6379)
@app.route(''/'')
def hello():
redis.incr(''hits'')
return ''Hello Container World! I have been seen %s times and my hostname is %s.\n'' % (redis.get(''hits''),socket.gethostname())
if __name__ == "__main__":
app.run(host="0.0.0.0", port=80, debug=True)
docker-compose up -d
curl 127.0.0.1:8080
docker-compose up --scale web=3 -d
案例:部署一个复杂的应用,投票系统,
源码:
/Users/apple/temp/docker-k8s-devops-master/chapter6/labs/example-voting-app
python 前端 + redis+java worker+ pg database + results app
cat docker-compose.yml
version: "3"
services:
voting-app:
build: ./voting-app/.
volumes:
- ./voting-app:/app
ports:
- "5000:80"
links:
- redis
networks:
- front-tier
- back-tier
result-app:
build: ./result-app/.
volumes:
- ./result-app:/app
ports:
- "5001:80"
links:
- db
networks:
- front-tier
- back-tier
worker:
build: ./worker
links:
- db
- redis
networks:
- back-tier
redis:
image: redis
ports: ["6379"]
networks:
- back-tier
db:
image: postgres:9.4
volumes:
- "db-data:/var/lib/postgresql/data"
networks:
- back-tier
volumes:
db-data:
networks:
front-tier: # 没指明 driver,默认为 bridge
back-tier:
docker-compose up
浏览器通过 5000 端口投票,5001 查看投票结果
docker-compose build #可以事先 build image, 而用 up 会先 build 再做 start。
docker swarm
创建一个 3 节点的 swarm cluster
manager 192.168.205.10
worker1 192.168.205.11
worker2 192.168.205.12
manager:
docker swarm init --advertise-addr=192.168.205.10
worker1 and 2:
docker swarm join xxxxx
manager:
docker node ls # 查看所有节点
docker service create --name demo busybox sh -c "while true;do sleep 3600;done"
docker service ls
docker service ps demo # 看 service 在哪台机器上
docker service scale demo=5 #扩展成 5 台
如果在 work2 上,强制删除了一个 container, docker rm -f xxxxxxxxx.
这时候如果 docker service ls,会显示 REPLICAS 4/5, 过一会儿会显示 5/5,在 docker service ls 里会显示有状态为 shutdown 的 container
docker service rm demo # 删除整个 service
docker service ps demo
swarm service 部署 WordPress
docker network create -d overlay demo # 创建 overlay 的网络,docker network ls
docker service create --name mysql --env MYSQL_ROOT_PASSWORD=root --env MYSQL_DATABASE=wordpress --network demo --mount type=volume,source=mysql-data,destination=/var/lib/mysql mysql #service 中 - v 是这样的 mount 格式,名字叫 mysql-data,挂载地址在 /var/lib/mysql
docker service ls
docker service ps mysql
docker service create --name wordpress -p 80:80 --env WORDPRESS_DB_PASSWORD=root --env WORDPRESS_DB_HOST=mysql --network demo wordpress
docker service ps wordpress
访问 manager 或者 worker 的 http 地址,都能访问到 wordpress
集群服务间通信之 RoutingMesh
swam 有内置服务发现的功能。通过 service 访问,是连到了 overlay 的网络。 用到了 vip。
首先要有 demo 的 overlay 网络。
docker service create --name whoami -p 8000:8000 --network demo -d jwilder/whoami
docker service ls
docker service ps whoami #运行在 manager 节点
curl 127.0.0.1:8000
再创建一个 busybox service
docker service create --name client -d --network demo busybox sh -c "while true;do sleep 3600;done"
docker service ls
docker service ps client #运行在 work1 节点
首先进到 swarm 的 worker1 节点
docker exec -it xxxx sh 进入这个 busybox container
ping whoami #ping service 的 name, 10.0.0.7, 这个其实是一个 vip,通过 lvs 创建的
docker service scale whoami=2 # 扩展到 2 台
docker service ps whoami #有一台运行在 work1,一台在 work2
进入 worker1 的节点
docker exec -it xxx sh #进入 busybox container
ping whoami # 还是不变
nslookup whoami # 10.0.0.7 虚拟 ip
nslookup tasks.whoami # 有 2 个地址。这才是具体 container 的真实地址
iptables -t mangle -nL DOCKER-INGRESS 里做了转发
Routing Mesh 的两种体现
Internal:在网络中,container 和 container 是通过 overlay 网络来进行通信。
Ingress:如果服务有绑定接口,则此服务可以通过任意 swarm 节点的响应接口访问。服务端口被暴露到每个 swarm 节点
docker stack 部署 wordpress
compose yml 的 reference:https://docs.docker.com/compose/compose-file/
官方例子:
version: "3.3"
services:
wordpress:
image: wordpress
ports:
- "8080:80"
networks:
- overlay
deploy:
mode: replicated
replicas: 2
endpoint_mode: vip #vip指service互访的时候,往外暴露的是虚拟的ip,底层通过lvs,负载均衡到后端服务器。默认为vip模式。
mysql:
image: mysql
volumes:
- db-data:/var/lib/mysql/data
networks:
- overlay
deploy:
mode: replicated
replicas: 2
endpoint_mode: dnsrr #dnsrr,直接使用service的ip地址,当横向扩展了以后,可能有三个或者四个IP地址,循环调用。
volumes:
db-data:
networks:
overlay:
还有 labels:打标签
mode:global 和 replicated,global 代表全 cluster 只有一个,不能做横向扩展。replicated,mode 的默认值,可以通过 docker service scale 做横向扩展。
placement:设定 service 的限定条件。比如:
version: ''3.3''
services:
db:
image: postgres
deploy:
placement:
constraints:
- node.role == manager #db这个service一定会部署到manager这个节点,并且系统环境一定是ubuntu 14.04
- engine.labels.operatingsystem == ubuntu 14.04
preferences:
- spread: node.labels.zone
replicas:如果设置了模式为 replicted,可以设置这个值
resources:资源占用和保留。
restart_policy: 重启条件,延迟,重启次数
update_config: 配置更新时的参数,比如可以同时更新 2 个,要等 10 秒才更新第二个。
cat docker-compose.yml
version: ''3''
services:
web: #这个 service 叫 web
image: wordpress
ports:
- 8080:80
environment:
WORDPRESS_DB_HOST: mysql
WORDPRESS_DB_PASSWORD: root
networks:
- my-network
depends_on:
- mysql
deploy:
mode: replicated
replicas: 3
restart_policy:
condition: on-failure
delay: 5s
max_attempts: 3
update_config:
parallelism: 1
delay: 10s
mysql: #这个 service 叫 mysql
image: mysql
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: wordpress
volumes:
- mysql-data:/var/lib/mysql
networks:
- my-network
deploy:
mode: global #指能创建一台,不允许 replicated
placement:
constraints:
- node.role == manager
volumes:
mysql-data:
networks:
my-network:
driver: overlay # 默认为 bridge,但是我们在多机集群里,要改成 overlay。
发布:
docker stack deploy wordpress --compose-file=docker-compose.yml #stack 的名字为 wordpress
查看:
docker stack ls
docker stack ps wordpress
docker stack services wordpress #显示 services replicas 的情况。
访问:随便挑一台 node 的 ip 8080 端口
注意:docker swarm 不能使用上面投票系统中的 build,所以要自己 build image
投票系统,使用 docker swarm 部署:
cat docker-compose.yml
version: "3"
services:
redis:
image: redis:alpine
ports:
- "6379"
networks:
- frontend
deploy:
replicas: 2
update_config:
parallelism: 2
delay: 10s
restart_policy:
condition: on-failure
db:
image: postgres:9.4
volumes:
- db-data:/var/lib/postgresql/data
networks:
- backend
deploy:
placement:
constraints: [node.role == manager]
vote:
image: dockersamples/examplevotingapp_vote:before
ports:
- 5000:80
networks:
- frontend
depends_on:
- redis
deploy:
replicas: 2
update_config:
parallelism: 2
restart_policy:
condition: on-failure
result:
image: dockersamples/examplevotingapp_result:before
ports:
- 5001:80
networks:
- backend
depends_on:
- db
deploy:
replicas: 1
update_config:
parallelism: 2
delay: 10s
restart_policy:
condition: on-failure
worker:
image: dockersamples/examplevotingapp_worker
networks:
- frontend
- backend
deploy:
mode: replicated
replicas: 1
labels: [APP=VOTING]
restart_policy:
condition: on-failure
delay: 10s
max_attempts: 3
window: 120s
placement:
constraints: [node.role == manager]
visualizer:
image: dockersamples/visualizer:stable
ports:
- "8080:8080"
stop_grace_period: 1m30s
volumes:
- "/var/run/docker.sock:/var/run/docker.sock"
deploy:
placement:
constraints: [node.role == manager]
networks:
frontend: # 在 swarm 模式下默认是 overlay 的
backend:
volumes:
db-data:
启动:
docker stack deploy voteapp --compose-file=docker-compose.yml
docker secret 管理
internal distributed store 是存储在所有 swarm manager 节点上的,所以 manager 节点推荐 2 台以上。存在 swarm manger 节点的 raft database 里。
secret 可以 assign 给一个 service,这个 service 就能看到这个 secret
在 container 内部 secret 看起来像文件,但是实际是在内存中。
secret 创建,从文件创建:
vim alexpasswd
admin123
docker secret create my-pw alexpasswd #给这个 secret 起个名字叫 my-pw
查看:
docker secret ls
从标准输入创建:
echo "adminadmin" | docker secret create my-pw2 - # 从标准输入创建
删除:
docker secret rm my-pw2
把一个 secret 暴露给 service
docker service create --name client --secret my-pw busybox sh -c while true;do sleep 3600;done"
查看 container 在哪个节点上:
docker service ps client
进入这个 container:
docker exec -it ccee sh
cd /run/secret/my-pw # 这里就能看到我们的密码 secret
例如 mysql 的 docker:
docker service create --name db --secret my-pw -e MYSQL_ROOT_PASSWORD_FILE=/run/secrets/my-pw mysql
secret 在 stack 中使用:
有个密码文件:
cat password
adminadmin
docker-compose.yml 文件:
version: ''3''
services:
web:
image: wordpress
ports:
- 8080:80
secrets:
- my-pw
environment:
WORDPRESS_DB_HOST: mysql
WORDPRESS_DB_PASSWORD_FILE: /run/secrets/my-pw
networks:
- my-network
depends_on:
- mysql
deploy:
mode: replicated
replicas: 3
restart_policy:
condition: on-failure
delay: 5s
max_attempts: 3
update_config:
parallelism: 1
delay: 10s
mysql:
image: mysql
secrets:
- my-pw
environment:
MYSQL_ROOT_PASSWORD_FILE: /run/secrets/my-pw
MYSQL_DATABASE: wordpress
volumes:
- mysql-data:/var/lib/mysql
networks:
- my-network
deploy:
mode: global
placement:
constraints:
- node.role == manager
volumes:
mysql-data:
networks:
my-network:
driver: overlay
# secrets:
# my-pw:
# file: ./password
使用:
docker stack deploy wordpress -c=docker-compose.yml
service 的更新:
首先建立源 service:
docker service create --name web --publish 8080:5000 --network demo alexhe/python-flask-demo:1.0
开始扩展,至少 2 个:
docker service scale web=2
检查服务 curl 127.0.0.1:8080
while true;do curl 127.0.0.1:8080 && sleep 1;done
更新服务:
可以更新 secret,publish port,image 等等
docker service update --image alexhe/python-flask-demo:2.0 web
更新端口:
docker service update --publish-rm 8080:5000 --publish-add 8088:5000 web
k8s 版本
Docker Kubernetes--services(微服务)
文章目录
- 1、services简介
- 2、IPVS模式的service
- 2.1 查看没有设置ipvs模式时候的ipvs
- 2.2 部署ipvs模式
- 2.3 测试(观察是否是动态负载均衡变化)
- 3、k8s提供的dns服务插件
- 4、Headless Service “无头服务”
- 5、从外部访问service的三种方式
- 5.1 NodePort方式
- 5.2 LoadBalancer
- 5.2.1没有Metallb
- 5.2.2 通过Metallb模拟云端环境
- 5.2.3 ingress结合metallb的实验
- 5.3 ExternalName(集群内部访问外部)
- 5.3.1 ExternalName
- 5.3.2 直接分配一个公有ip
1、services简介
- Service可以看作是一组提供相同服务的Pod对外的访问接口。借助Service,应用可以方便地实现服务发现和负载均衡。
service默认只支持4层负载均衡能力,没有7层功能。(可以通过Ingress实现)
service的类型:(前三种是集群外部访问内部资源)
ClusterIP:默认值,k8s系统给service自动分配的虚拟IP,只能在集群内部访问。
NodePort:将Service通过指定的Node上的端口暴露给外部,访问任意一个NodeIP:nodePort都将路由到ClusterIP。
LoadBalancer:在 NodePort 的基础上,借助 cloud provider 创建一个外部的负载均衡器,并将请求转发到 <NodeIP>:NodePort,此模式只能在云服务器上使用。
ExternalName:将服务通过 DNS CNAME 记录方式转发到指定的域名(通过 spec.externlName 设定)。[集群内部访问外部,通过内部调用外部资源]
2、IPVS模式的service
- Service 是由 kube-proxy 组件,加上 iptables 来共同实现的.
kube-proxy 通过 iptables 处理 Service 的过程,需要在宿主机上设置相当多的 iptables 规则,如果宿主机有大量的Pod,不断刷新iptables规则,会消耗大量的cpu资源。
PVS模式的service,可以使K8s集群支持更多量级的Pod。
2.1 查看没有设置ipvs模式时候的ipvs
[root@server2 ~]# lsmod | grep ip
ip6_udp_tunnel 12755 1 vxlan
ip_vs_sh 12688 0
ip_vs_wrr 12697 0
ip_vs_rr 12600 0
ip_vs 145458 6 ip_vs_rr,ip_vs_sh,ip_vs_wrr
2.2 部署ipvs模式
[root@server2 ~]# yum install -y ipvsadm ##安装ipvsadm,每个节点都需要安装。每个节点操作一样
[root@server3 ~]# yum install -y ipvsadm
[root@server4 ~]# yum install -y ipvsadm
[root@server2 ~]# kubectl get cm -n kube-system
[root@server2 ~]# kubectl get pod -n kube-system | grep kube-proxy ##部署之前查看一下
[root@server2 ~]# kubectl -n kube-system edit cm kube-proxy ##进入修改mode为ipvs
mode: "ipvs"
[root@server2 ~]# kubectl get pod -n kube-system |grep kube-proxy | awk '{system("kubectl delete pod "$1" -n kube-system")}' ##更新kube-proxy pod
[root@server2 ~]# kubectl get pod -n kube-system | grep kube-proxy ##部署之后查看是否发生变化
#IPVS模式下,kube-proxy会在service创建后,在宿主机上添加一个虚拟网卡:kube-ipvs0,并分配service IP。
[root@server2 ~]# ip addr ##查看ip
[root@server2 ~]# kubectl expose deployment deployment --port=80
service/deployment exposed
[root@server2 ~]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
deployment ClusterIP 10.98.150.51 <none> 80/TCP 5s
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 28d
[root@server2 ~]# kubectl create -f service.yml
service/myservice created
[root@server2 ~]# ipvsadm -ln
[root@server2 ~]# iptables -t nat -nL | grep :80
[root@server2 ~]#
2.3 测试(观察是否是动态负载均衡变化)
[root@server2 ~]# cat service.yml rs.yml > demo.yml
[root@server2 ~]# vim demo.yml
[root@server2 ~]# kubectl get pod -L app
[root@server2 ~]# vim demo.yml
---
apiVersion: v1
kind: Service
Metadata:
name: myservice
spec:
selector:
app: myapp
ports:
- protocol: TCP
port: 80
targetPort: 80
---
apiVersion: apps/v1
kind: Deployment
Metadata:
name: demo2
spec:
replicas: 3
selector:
matchLabels:
app: myapp
template:
Metadata:
labels:
app: myapp
spec:
containers:
- name: myapp
image: myapp:v2
[root@server2 ~]# kubectl apply -f demo.yml ##创建services和pod
service/myservice created
deployment.apps/demo2 created
[root@server2 ~]# kubectl get svc ##查看服务
[root@server2 ~]# kubectl describe svc myservice
[root@server2 ~]# ip addr
[root@server2 ~]# ipvsadm -ln ##查看对应的负载均衡
[root@server2 ~]# curl 10.108.244.104/hostname.html
demo2-67f8c948cf-qv8cl
[root@server2 ~]# curl 10.108.244.104/hostname.html
demo2-67f8c948cf-wcrlp
[root@server2 ~]# curl 10.108.244.104/hostname.html
demo2-67f8c948cf-f2zxw
3、k8s提供的dns服务插件
[root@server2 ~]# kubectl get services kube-dns --namespace=kube-system
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kube-dns ClusterIP 10.96.0.10 <none> 53/UDP,53/TCP,9153/TCP 28d
[root@server2 ~]# kubectl attach demo -it ##如果有demo就直接进
[root@server2 ~]# kubectl run demo --image=busyBoxplus -it ##没有demo创建demo
[root@server2 ~]# yum install bind-utils -y ##安装dig工具
[root@server2 ~]# dig myservice.default.svc.cluster.local. @10.96.0.10 ##通过dig进行测试
4、Headless Service “无头服务”
- Headless Service不需要分配一个VIP,而是直接以DNS记录的方式解析出被代理Pod的IP地址。
域名格式: ( s e r v i c e n a m e ) . (servicename). (servicename).(namespace).svc.cluster.local
[root@server2 ~]# vim demo.yml
clusterIP: None ##无头服务
replicas: 6
[root@server2 ~]# kubectl apply -f demo.yml
service/myservice created
deployment.apps/demo2 created
[root@server2 ~]# kubectl get pod
[root@server2 ~]# kubectl delete -f rs.yml
deployment.apps "deployment" deleted
[root@server2 ~]# kubectl delete svc deployment
service "deployment" deleted
[root@server2 ~]# kubectl get svc ##CLUSTER-IP没有分配ip
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 28d
myservice ClusterIP None <none> 80/TCP 107s
[root@server2 ~]# kubectl describe svc myservice ##有对应的Endpoints:
[root@server2 ~]# kubectl get pod
[root@server2 ~]# kubectl attach demo -it
5、从外部访问service的三种方式
5.1 NodePort方式
[root@server2 ~]# kubectl delete -f demo.yml
service "myservice" deleted
deployment.apps "demo2" deleted
[root@server2 ~]# vim demo.yml
#clusterIP: None
type: NodePort
replicas: 3
[root@server2 ~]# kubectl apply -f demo.yml
service/myservice created
deployment.apps/demo2 created
[root@server2 ~]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 28d
myservice NodePort 10.105.12.247 <none> 80:30942/TCP 25s
[root@server2 ~]# netstat -antlp| grep :30942
tcp 0 0 0.0.0.0:30942 0.0.0.0:* LISTEN 30455/kube-proxy
[root@foundation50 yum.repos.d]# curl 192.168.0.2:30942/hostname.html
[root@server2 ~]# ipvsadm -ln
5.2 LoadBalancer
[root@server2 ~]# vim demo.yml
[root@server2 ~]# kubectl apply -f demo.yml
service/myservice configured
deployment.apps/demo2 unchanged
#type: NodePort
type: LoadBalancer
[root@server2 ~]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 28d
myservice LoadBalancer 10.105.12.247 <pending> 80:30942/TCP 7m40s
[root@server2 ~]# ipvsadm -ln
[root@server2 ~]# kubectl describe svc myservice
[root@server2 ~]# kubectl delete svc myservice
service "myservice" deleted
[root@server2 ~]# kubectl apply -f demo.yml
service/myservice created
deployment.apps/demo2 unchanged
[root@server2 ~]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 28d
myservice LoadBalancer 10.100.19.229 <pending> 80:30105/TCP 2s
5.2.1没有Metallb
5.2.2 通过Metallb模拟云端环境
5.2.3 ingress结合Metallb的实验
5.3 ExternalName(集群内部访问外部)
5.3.1 ExternalName
5.3.2 直接分配一个公有ip
docker – Kubectl:Kubernetes与minikube超时
我已经安装了minikube并启动了它内置的Kubernertes集群
$minikube start
Starting local Kubernetes cluster...
Kubernetes is available at https://192.168.99.100:443.
Kubectl is Now configured to use the cluster.
我也安装了kubectl
$kubectl version
Client Version: version.Info{Major:"1",Minor:"3",GitVersion:"v1.3.0",GitCommit:"283137936a498aed572ee22af6774b6fb6e9fd94",GitTreeState:"clean",BuildDate:"2016-07-01T19:26:38Z",GoVersion:"go1.6.2",Compiler:"gc",Platform:"linux/amd64"}
但我无法成功使用kubectl与正在运行的Kubernetes集群交谈
$kubectl get nodes
Unable to connect to the server: net/http: TLS handshake timeout
编辑
$minikube logs
E0712 19:02:08.767815 1257 docker_manager.go:1955] Failed to create pod infra container: ImagePullBackOff; Skipping pod "kube-addon-manager-minikubevm_kube-system(48abed82af93bb0b941173334110923f)": Back-off pulling image "gcr.io/google_containers/pause-amd64:3.0"
E0712 19:02:08.767875 1257 pod_workers.go:183] Error syncing pod 48abed82af93bb0b941173334110923f,skipping: Failed to "StartContainer" for "POD" with ImagePullBackOff: "Back-off pulling image \"gcr.io/google_containers/pause-amd64:3.0\""
E0712 19:02:23.767380 1257 docker_manager.go:1955] Failed to create pod infra container: ImagePullBackOff; Skipping pod "kube-addon-manager-minikubevm_kube-system(48abed82af93bb0b941173334110923f)": Back-off pulling image "gcr.io/google_containers/pause-amd64:3.0"
E0712 19:02:23.767464 1257 pod_workers.go:183] Error syncing pod 48abed82af93bb0b941173334110923f,skipping: Failed to "StartContainer" for "POD" with ImagePullBackOff: "Back-off pulling image \"gcr.io/google_containers/pause-amd64:3.0\""
E0712 19:02:36.766696 1257 docker_manager.go:1955] Failed to create pod infra container: ImagePullBackOff; Skipping pod "kube-addon-manager-minikubevm_kube-system(48abed82af93bb0b941173334110923f)": Back-off pulling image "gcr.io/google_containers/pause-amd64:3.0"
E0712 19:02:36.766760 1257 pod_workers.go:183] Error syncing pod 48abed82af93bb0b941173334110923f,skipping: Failed to "StartContainer" for "POD" with ImagePullBackOff: "Back-off pulling image \"gcr.io/google_containers/pause-amd64:3.0\""
E0712 19:02:51.767621 1257 docker_manager.go:1955] Failed to create pod infra container: ImagePullBackOff; Skipping pod "kube-addon-manager-minikubevm_kube-system(48abed82af93bb0b941173334110923f)": Back-off pulling image "gcr.io/google_containers/pause-amd64:3.0"
E0712 19:02:51.767672 1257 pod_workers.go:183] Error syncing pod 48abed82af93bb0b941173334110923f,skipping: Failed to "StartContainer" for "POD" with ImagePullBackOff: "Back-off pulling image \"gcr.io/google_containers/pause-amd64:3.0\""
E0712 19:03:02.766548 1257 docker_manager.go:1955] Failed to create pod infra container: ImagePullBackOff; Skipping pod "kube-addon-manager-minikubevm_kube-system(48abed82af93bb0b941173334110923f)": Back-off pulling image "gcr.io/google_containers/pause-amd64:3.0"
E0712 19:03:02.766609 1257 pod_workers.go:183] Error syncing pod 48abed82af93bb0b941173334110923f,skipping: Failed to "StartContainer" for "POD" with ImagePullBackOff: "Back-off pulling image \"gcr.io/google_containers/pause-amd64:3.0\""
E0712 19:03:16.766831 1257 docker_manager.go:1955] Failed to create pod infra container: ImagePullBackOff; Skipping pod "kube-addon-manager-minikubevm_kube-system(48abed82af93bb0b941173334110923f)": Back-off pulling image "gcr.io/google_containers/pause-amd64:3.0"
E0712 19:03:16.766904 1257 pod_workers.go:183] Error syncing pod 48abed82af93bb0b941173334110923f,skipping: Failed to "StartContainer" for "POD" with ImagePullBackOff: "Back-off pulling image \"gcr.io/google_containers/pause-amd64:3.0\""
E0712 19:04:15.829223 1257 docker_manager.go:1955] Failed to create pod infra container: ErrImagePull; Skipping pod "kube-addon-manager-minikubevm_kube-system(48abed82af93bb0b941173334110923f)": image pull Failed for gcr.io/google_containers/pause-amd64:3.0,this may be because there are no credentials on this request. details: (Error response from daemon: Get https://gcr.io/v1/_ping: dial tcp 74.125.28.82:443: I/O timeout)
E0712 19:04:15.829326 1257 pod_workers.go:183] Error syncing pod 48abed82af93bb0b941173334110923f,skipping: Failed to "StartContainer" for "POD" with ErrImagePull: "image pull Failed for gcr.io/google_containers/pause-amd64:3.0,this may be because there are no credentials on this request. details: (Error response from daemon: Get https://gcr.io/v1/_ping: dial tcp 74.125.28.82:443: I/O timeout)"
E0712 19:04:31.767536 1257 docker_manager.go:1955] Failed to create pod infra container: ImagePullBackOff; Skipping pod "kube-addon-manager-minikubevm_kube-system(48abed82af93bb0b941173334110923f)": Back-off pulling image "gcr.io/google_containers/pause-amd64:3.0"
一个.您需要确保与VM一起运行的docker守护程序可以通过代理连接到Internet.
湾您需要确保在主机上运行的kubectl可以在不通过代理的情况下到达VM
使用默认的kubectl示例
>确保将代理传递到由minikube创建的VM(这可确保VM中的docker守护程序可以访问Internet)
minikube start –vm-driver =“kvm”–docker-env =“http_proxy = xxx”–docker-env =“https_proxy = yyy”start
注意:使用代理设置替换xxx和yyy
>获取VM在启动时获得的IP.
minikube ip
注意:每次设置minikube都需要这样做,因为它可以改变
>确保kubectl可以在不进入代理的情况下与此VM通信
export no_proxy =“127.0.0.1,[minikube_ip]”
>现在启动POD并测试它
kubectl run hello-minikube –image = gcr.io / google_containers / echoserver:1.4 –port = 8080
kubectl公开部署hello-minikube –type = NodePort
kubectl获取pod
curl $(minikube service hello-minikube –url)
今天关于weblogic 部署 —— 从 docker 到 kubernetes和docker weblogic使用的讲解已经结束,谢谢您的阅读,如果想了解更多关于docker for mac 安装 kubernetes、kubernetes dashboard、docker kubernetes Swarm 容器编排 k8s CICD 部署 麦兜、Docker Kubernetes--services(微服务)、docker – Kubectl:Kubernetes与minikube超时的相关知识,请在本站搜索。
本文标签: