{"id":16615307,"url":"https://github.com/jonmosco/pause_container","last_synced_at":"2026-02-15T13:34:54.389Z","repository":{"id":68952092,"uuid":"210657374","full_name":"jonmosco/pause_container","owner":"jonmosco","description":null,"archived":false,"fork":false,"pushed_at":"2019-09-24T17:18:46.000Z","size":3,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-10-10T01:26:31.307Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jonmosco.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-09-24T17:12:59.000Z","updated_at":"2019-09-24T17:18:48.000Z","dependencies_parsed_at":null,"dependency_job_id":"704ced02-3c05-4dab-b2ac-19dfccf0c52d","html_url":"https://github.com/jonmosco/pause_container","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/jonmosco/pause_container","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jonmosco%2Fpause_container","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jonmosco%2Fpause_container/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jonmosco%2Fpause_container/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jonmosco%2Fpause_container/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jonmosco","download_url":"https://codeload.github.com/jonmosco/pause_container/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jonmosco%2Fpause_container/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29479931,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-15T11:35:25.641Z","status":"ssl_error","status_checked_at":"2026-02-15T11:34:57.128Z","response_time":118,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-12T02:09:10.532Z","updated_at":"2026-02-15T13:34:54.358Z","avatar_url":"https://github.com/jonmosco.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"### Understanding Kubernetes pods with the pause container\n\nThis repo contains the files necessary to understand what a pod is\nin Kubernetes, using Docker and the Google pause container.\n\nIf you prefer depth-first style of learning, really want the low-level\ndetails of how things work, then this repo is for you.\n\nBackground\n\nPods\n\nPods in Kubernetes (k8s from here on out to save me from all the typing), are\na group of one or more containers.  They share the IPC, and UTS namespaces.\n\nIn k8s 1.7+, shared PID namespace is enabled if the cluster is running\nDocker 1.13.1+, but has been reverted in 1.8, thus each container in a pod\nwill have to handle signals properly.\n\nYour Kubernetes server must be at or later than version v1.10\n\nAs of 1.16, Process Namespace Sharing is a beta feature that is enabled by\ndefault. It may be disabled by setting --feature-gates=PodShareProcessNamespace=false\n\n### Namespaces\n\nFrom namespaces(7):\n\n```\nDESCRIPTION\n       A  namespace  wraps  a global system resource in an abstraction that makes it appear to the processes within\n       the namespace that they have their own isolated instance of the global  resource.   Changes  to  the  global\n       resource  are  visible to other processes that are members of the namespace, but are invisible to other pro-\n       cesses.  One use of namespaces is to implement containers.\n```\n\n### Namespace sharing\n\nThe following namespaces will be described to detail how pods are created:\n\n* network\n* IPC\n* PID\n* UTS\n\n### Network namespace\n\n```\n--net=container:name\n```\n\n### IPC Namespace\n\n```\n--ipc=container:name\n```\n\nThe causes the container to join the specified containers IPC namespace.\nIPC (POSIX/SysV IPC) namespace provides separation of named shared\nmemory segments, semaphores and message queues.\n\nThey can even use IPC or send each other signals like HUP or TERM\n(With shared PID namespaces in Kubernetes 1.7, Docker \u003e=1.13)\n\n### UTS Namespace\n\nWhen namespace sharing is used, each container has the same hostname as the\nfirst container (the pause container in this cause) and the same IP.\n\n### PID Namespace\n\nEach container by default gets its own process namespace.\n\nWhile in k8s PID namespace sharing is not enabled, examples are included here\nfor sake of brevity.\n\nThis causes the container to join the specified containers PID namespace:\n\n```\n--pid=container:name\n```\n\nPID namespaces can not see into their peers namespace.  New PID namespace\nstarts at 1, and has representation in all the parent namespace, and can\nbe monitored as such.  In this example, pause assumes PID 1, and nginx,\nand ghost all become children of pause.\n\nInside the nginx container:\n\n```\nroot@88abb5cfad6f:/# ps -ef\nUID        PID  PPID  C STIME TTY          TIME CMD\nroot         1     0  0 14:44 ?        00:00:00 /pause\nroot         7     0  0 14:44 ?        00:00:00 nginx: master process nginx -g daemon off;\nnginx       13     7  0 14:44 ?        00:00:00 nginx: worker process\n1000        14     0  0 14:44 ?        00:00:02 node current/index.js\nroot        92     0  0 19:50 pts/0    00:00:00 /bin/bash\nroot       395    92  0 19:51 pts/0    00:00:00 ps -ef\n```\n\nInside the ghost container:\n\n```\nroot@88abb5cfad6f:/var/lib/ghost# ps -ef\nUID        PID  PPID  C STIME TTY          TIME CMD\nroot         1     0  0 14:44 ?        00:00:00 /pause\nroot         7     0  0 14:44 ?        00:00:00 nginx: master process nginx -g daemon off;\nsystemd+    13     7  0 14:44 ?        00:00:00 nginx: worker process\nnode        14     0  0 14:44 ?        00:00:02 node current/index.js\nroot       396     0  0 19:51 pts/0    00:00:00 /bin/bash\nroot       403   396  0 19:52 pts/0    00:00:00 ps -ef\nroot@88abb5cfad6f:/var/lib/ghost#\n```\n\nWhen tailing the logs for pause, we can watch the process termination.\nRunning docker stop will send a SIGTERM, and after a grace period, it\nsends SIGKILL:\n\n```\ndocker logs -f 88abb5cfad6f\n\n\nshutting down, got signal: Terminated\n```\n\nOn a Kubernetes cluster, the containers that make up this pod all share the same IP address:\n\n```\nworker01# docker exec -ti \u003ccontainer_id\u003e ip a\n1: lo: \u003cLOOPBACK,UP,LOWER_UP\u003e mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000\n    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00\n    inet 127.0.0.1/8 scope host lo\n       valid_lft forever preferred_lft forever\n    inet6 ::1/128 scope host\n       valid_lft forever preferred_lft forever\n3: eth0@if11: \u003cBROADCAST,MULTICAST,UP,LOWER_UP\u003e mtu 1450 qdisc noqueue state UP group default\n    link/ether 0a:58:0a:02:07:0c brd ff:ff:ff:ff:ff:ff\n    inet 10.2.7.12/24 scope global eth0\n       valid_lft forever preferred_lft forever\n    inet6 fe80::384f:f6ff:fe26:5953/64 scope link\n       valid_lft forever preferred_lft forever\n\nworker01 ~ # docker exec -ti \u003ccontainer_id\u003e ip a\n1: lo: \u003cLOOPBACK,UP,LOWER_UP\u003e mtu 65536 qdisc noqueue state UNKNOWN qlen 1000\n    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00\n    inet 127.0.0.1/8 scope host lo\n       valid_lft forever preferred_lft forever\n    inet6 ::1/128 scope host\n       valid_lft forever preferred_lft forever\n3: eth0@if11: \u003cBROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN\u003e mtu 1450 qdisc noqueue state UP\n    link/ether 0a:58:0a:02:07:0c brd ff:ff:ff:ff:ff:ff\n    inet 10.2.7.12/24 scope global eth0\n       valid_lft forever preferred_lft forever\n    inet6 fe80::384f:f6ff:fe26:5953/64 scope link\n       valid_lft forever preferred_lft forever\n\nworker01 ~ # docker exec -ti \u003ccontainer_id\u003e ip a\n1: lo: \u003cLOOPBACK,UP,LOWER_UP\u003e mtu 65536 qdisc noqueue qlen 1000\n    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00\n    inet 127.0.0.1/8 scope host lo\n       valid_lft forever preferred_lft forever\n    inet6 ::1/128 scope host\n       valid_lft forever preferred_lft forever\n3: eth0@if11: \u003cBROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN\u003e mtu 1450 qdisc noqueue\n    link/ether 0a:58:0a:02:07:0c brd ff:ff:ff:ff:ff:ff\n    inet 10.2.7.12/24 scope global eth0\n       valid_lft forever preferred_lft forever\n    inet6 fe80::384f:f6ff:fe26:5953/64 scope link\n       valid_lft forever preferred_lft forever\npltecworker02 ~ #\n```\n\n## The pause() system call\n\nThe pause() system call puts a process to sleep until it receives a signal\nthat either is handled or terminates the process.  pause() returns only\nif a signal is received, in which case the signal is handled, and pause()\nreturns -1 and sets errno to EINTR.  If the kernel raises an ignored\nsignal, the process does not wake up.  It performs only two actions:\n\n1. It puts the process in the interruptible sleep state\n2. It calls schedule() to invoke the Linux process scheduler to find\n   another process to run.  As the process is not actually waiting for anything,\n   the kernel will not wake up unless it receives a signal.\n\n## The pause container\n\nThe pause container provides a very simple program that assumes the role of\nof PID 1.  It sleeps and watches for zombie processes.\n\nThe code for this is pause.c and is in this repo.\n\nThe sigreap() function will wait for any child process:\n\n```\nstatic void sigreap(int signo) {\n  while (waitpid(-1, NULL, WNOHANG) \u003e 0);\n}\n```\n\nwaitpid with arg pid=-1 means whatever can be reaped then WNOHANG means do not wait\nso it will reap all child processes (any that are zombies) then return -1 when there\nare none left, then return you can bind that signal handler on delivery of certain signals\ne.g SIGCHLD sigaction(SIGCHLD, sigreap, ...)\nthe means, change the action upon reception of a SIGCHLD signal from the default to running sigreap()\n\n## Creating a pod outside k8s\n\nCreating the pod with docker:\n\n```\n$ docker run -d --name pause -p 8080:80 gcr.io/google_containers/pause-amd64:3.0\n$ docker run -d --name nginx -v `pwd`/nginx.conf:/etc/nginx/nginx.conf --net=container:pause --ipc=container:pause --pid=container:pause nginx\n$ docker run -d --name ghost --net=container:pause --ipc=container:pause --pid=container:pause ghost\n```\n\nCreating the pod with docker compose:\n\n```\n$ docker-compose up -d\n```\n\nUsing the Makefile:\n\n```\n$ make pod\n$ make stop\n$ make clean\n```\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjonmosco%2Fpause_container","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjonmosco%2Fpause_container","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjonmosco%2Fpause_container/lists"}