Docker Fundamentals: Cgroup

Linux Namespace的技术解决了环境隔离的问题,不过这是虚拟化最基本的一步,我们另外需要解决对计算机资源使用上的隔离。说人话,就是虽然Namespace把我关到一个特定的环境,但是里面进程使用的CPU、内存、磁盘等计算资源实际上没有被限制。这个问题的解决,就要用到CGroup技术。 Linux CGroup全称是Linux Control Group,也是其内核的一个功能,用于限制、控制和分离一个进程group的资源。最早这个项目是2006年由谷歌的工程师发起的,最开始名称是process containers(工程容器),后面觉得内核中容器这个名词被用烂了,就改名为cgroup。 CGroup可以让你对系统中运行的进程的用户组分配资源-CPU时间、系统内存、网络带宽亦或者是这些的组合。同时,也可以监控你配置的cgroup,拒绝cgroup访问某些资源。主要提供的功能如下: Resource Limitation: 限制资源使用 Prioritization: 优先级控制,例如CPU使用和磁盘IO吞吐 Accounting:审计统计,主要用于计费 Control:挂起进程,恢复执行进程 在真正的实践当中,system admin一般会利用CGroup做以下的事: 对进程集合进行隔离,限制他们所消费的资源,例如绑定CPU core 为这组进程分配足够使用的内存 为这组进程分配响应的网络带宽和磁盘存储限制 限制访问某些设备(白名单) Linux实际上把CGroup实现成了一个文件系统,你可以mount。在linux环境输入下面的可以看到cgroup已经为你mount好: 1 2 3 4 5 6 7 8 9 10 11 12 derios@ubuntu:~$ mount -t cgroup cgroup on /sys/fs/cgroup/cpuset type cgroup (rw,relatime,cpuset) cgroup on /sys/fs/cgroup/cpu type cgroup (rw,relatime,cpu) cgroup on /sys/fs/cgroup/cpuacct type cgroup (rw,relatime,cpuacct) cgroup on /sys/fs/cgroup/memory type cgroup (rw,relatime,memory) cgroup on /sys/fs/cgroup/devices type cgroup (rw,relatime,devices) cgroup on /sys/fs/cgroup/freezer type cgroup (rw,relatime,freezer) cgroup on /sys/fs/cgroup/blkio type cgroup (rw,relatime,blkio) cgroup on /sys/fs/cgroup/net_prio type cgroup (rw,net_prio) cgroup on /sys/fs/cgroup/net_cls type cgroup (rw,net_cls) cgroup on /sys/fs/cgroup/perf_event type cgroup (rw,relatime,perf_event) cgroup on /sys/fs/cgroup/hugetlb type cgroup (rw,relatime,hugetlb) 可以看到,在/sys/fs下有cgroup目录,这个目录下面有各种子目录:cpu,cpuset,memory…。这些都是cgroup的子系统,分别用来干不同的事。 ...

April 5, 2021 · 4 min · 848 words · Me

Docker Fundamentals: Namespace

容器技术出现已经很久,只不过Docker容器平台的出现它变火了。Docker是第一个让容器能在不同机器之间移植的系统,它简化了打包应用的流程,也简化了打包应用的库和各种依赖。思考下整个OS的file system能直接被打包成一个简单的可移植的包,一开始的时候概念上还是很有趣的。 有时候我认为自己的阅读比较碎片化(short-term memory越来越少),所以我想把之前学习容器知识的一些基础技术再整理出来,也算是给自己学习的反馈。这个基础系列从Linux Namespace开始,后续会陆续介绍比如cgroup、aufs、devicemapper等技术。 参考 Namespace in operation Linux namespace man page Introduction to linux namespace 什么是Namespace 简单来说,linux namespace是Linux提供的一种内核级别环境隔离的方法。在早期的Unix中,提供了一种叫做chroot的系统调用:通过修改root目录把用户关到一个特定的目录下面。这种就是简单的隔离方式,也就是chroot内部的file system无法访问外部的内容。Linux Namespace在此基础之上,提供了对UTS、IPC、mount、network、PID、User等隔离机制。 这里可以简单举例,比如Linux的超级父进程的PID为1,如果我们可以把用户的进程空间关到某个进程分支之下,并且像chroot那样能够让下面的进程看到那个超级父进程的PID为1,而不同PID Namespace中的进程无法看到彼此,这样就能达到进程隔离。 Linux Namespace有以下的种类,供给后续参考(刚看有个印象就行): 分类 系统调用参数 相关内核版本 Mount namespaces CLONE_NEWNS Linux 2.4.19 UTS namespaces CLONE_NEWUTS Linux 2.6.19 IPC namespaces CLONE_NEWIPC Linux 2.6.19 PID namespaces CLONE_NEWPID Linux 2.6.24 Network namespaces CLONE_NEWNET 始于Linux 2.6.24 完成于 Linux 2.6.29 User namespaces CLONE_NEWUSER 始于 Linux 2.6.23 完成于 Linux 3.8) 其主要涉及到三个系统调用: clone(): 实现线程的系统调用,用来创建新的线程,并可通过涉及上述参数做到隔离 unshare(): 让某一个线程脱离某namespace setns(): 把某一个线程加到某namespace 如果读者你想看具体的实例,请自己man一下(关注一下自己的linux虚拟机内核),或者google一下,我这里贴一个clone()的source code: ...

April 1, 2021 · 11 min · 2282 words · Me

Kubernetes Handbook (Start & Pod)

使用minikube构建本地单节点k8s集群 minikube ssh kubectl cluster-info kubectl get nodes #查看节点信息 kubectl describe node minikube #详细信息 多节点k8s集群,使用Google K8s Engine 构建方式看GKE官网即可 k8s初步使用 kubectl run kubia –image=derios/kubia –port=8080 –generator=run/v1 --image=derios/kubia代表要运行的容器镜像 这里的--generator会被废弃,其含义指代的是创建一个ReplicationController而不是Deployment。 kubectl apply -f 更常用 kubectl get pods kubectl get pods -o wide 显示pod ip和pod的节点 如果使用GWE,可以访问集群的dashborad: kubectl clusert-info获取地址 gcloud container clusters describe kubia | grep -E “(username|password):“获取用户名和密码 如果仅仅使用minikube,则如下不需要任何凭证即可访问: 1 minikube dashboard Namespace相关操作 1 kubectl config set-context --current --namespace=my-namespace 创建服务对象,访问Web应用 如果使用minikube或者kubeadm等自定义k8s,loadbalancer是没有集成的,需要AWS或者Google Cloud。最好使用NodePort或者Ingress Controller。如果真要用minikube, 可以使用minikube tunnel解决, 或者minikube service kubia-http ...

March 31, 2021 · 6 min · 1100 words · Me

Docker Cheat Sheet

Books Docker in Action (English ver.) Docker入门到实践(中文) 速查 Docker Cheat Sheet 全量CLI 容器管理CLI 查看容器CLI 容器交互CLI 镜像管理CLI 镜像传输CLI DOCKERFILE主要命令 Dockerfile 基底 1 FROM ruby:2.2.2 变量 1 2 ENV APP_HOME/myapp RUN mkdir $APP_HOME 初始化 1 RUN bundle install 1 WORKDIR /myapp 1 2 VOLUME ["/data"] # Specification for mount point 1 2 ADD file.xyz /file.xyz COPY --chown=user:group host_file.xyz /path/container_file.xyz Onbuild 1 2 ONBUILD RUN bundle install # when used with another file 命令 1 2 EXPOSE 5900 CMD ["bundle", "exec", "rails", "server"] Entrypoint 1 ENTRYPOINT exec top -b Metadata 1 LABEL version="1.0" 1 2 LABEL "com.example.vendor"="ACME Incorporated" LABEL com.example.label-with-value="foo" 1 2 LABEL description="This text illustrates \ that label-values can span multiple lines." Docker Compose 基本用法 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 # docker-compose.yml version: '2' services: web: build: . # build from Dockerfile context: ./Path dockerfile: Dockerfile ports: - "5000:5000" volumes: - .:/code redis: image: redis 指令 1 2 docker-compose start docker-compose stop 1 2 docker-compose pause docker-compose unpause 1 2 3 docker-compose ps docker-compose up docker-compose down Reference(例子) 构建 1 2 3 web: # build from Dockerfile build: . 1 2 3 4 # build from custom Dockerfile build: context: ./dir dockerfile: Dockerfile.dev 1 2 3 4 5 6 # build from image image: ubuntu image: ubuntu:14.04 image: tutum/influxdb image: example-registry:4000/postgresql image: a4bc65fd 端口 1 2 3 ports: - "3000" - "8000:80" # guest:host 1 2 # expose ports to linked services (not to host) expose: ["3000"] 指令 1 2 3 # command to execute command: bundle exec thin -p 3000 command: [bundle, exec, thin, -p, 3000] 1 2 3 # override the entrypoint entrypoint: /app/start.sh entrypoint: [php, -d, vendor/bin/phpunit] 环境变量 1 2 3 4 5 # environment vars environment: RACK_ENV: development environment: - RACK_ENV=development 1 2 3 # environment vars from file env_file: .env env_file: [.env, .development.env] 依赖 1 2 3 4 5 # makes the `db` service available as the hostname `database` # (implies depends_on) links: - db:database - redis 1 2 3 # make sure `db` is alive before starting depends_on: - db 其他选项 1 2 3 4 # make this service extend another extends: file: common.yml # optional service: webapp 1 2 3 volumes: - /var/lib/mysql - ./_data:/var/lib/mysql 高级特性 打标签 1 2 3 4 services: web: labels: com.example.description: "Accounting web app" DNS服务器 1 2 3 4 5 6 services: web: dns: 8.8.8.8 dns: - 8.8.8.8 - 8.8.4.4 设备绑定 1 2 3 4 services: web: devices: - "/dev/ttyUSB0:/dev/ttyUSB0" 外部链接 1 2 3 4 5 services: web: external_links: - redis_1 - project_db_1:mysql 主机设置 1 2 3 4 services: web: extra_hosts: - "somehost:192.168.1.100" Services 1 2 3 4 5 6 7 8 9 10 11 # To view list of all the services runnning in swarm docker service ls # To see all running services docker stack services stack_name # to see all services logs docker service logs stack_name service_name # To scale services quickly across qualified node docker service scale stack_name_service_name=replicas Clean up 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 # To clean or prune unused (dangling) images docker image prune # To remove all images which are not in use containers , add - a docker image prune -a # To Purne your entire system docker system prune # To leave swarm docker swarm leave # To remove swarm ( deletes all volume data and database info) docker stack rm stack_name # To kill all running containers docker kill $(docekr ps -q )

March 30, 2021 · 3 min · 584 words · Me