├── README.md ├── deployment └── deployment.yaml ├── replicaset └── replicaset.yaml └── simple ├── go.mod ├── go.sum ├── main.go └── simple.yaml /README.md: -------------------------------------------------------------------------------- 1 | # Anatomy of a Pod 2 | 3 | ## A little bit of history 4 | 5 | ### The 80's with `chroot` 6 | 7 | During the 80's, the `chroot` Unix system call is created, to give a process and its children a root filesystem different from the system root filesystem. This way, the processes are not able to access, by their name, files outside of this new root filesystem (but, and that's another story, there exist some indirect ways to access files outside of this new root filesystem). 8 | 9 | This isolation is specifically useful for two use cases: 10 | 11 | - you want to test a new system, based on a fresh new filesystem, without the need to reboot your computer and kernel, 12 | - you want to run a service on a system with the guarantee that the service will have access to a part of the filesystem only. 13 | 14 | To experiment, we will create a very small system, based on the `busybox` tool. 15 | 16 | - be sure the `busybox` is installed on your system, for example on a Debian-based system: 17 | ``` 18 | $ sudo apt install busybox-static 19 | ``` 20 | 21 | - create a new directory and create the necessary files to be able to run some commands: 22 | ``` 23 | $ mkdir newroot 24 | $ cd newroot 25 | $ mkdir bin proc 26 | $ cd bin 27 | $ cp $(which busybox) . 28 | $ ln -s busybox sh 29 | $ ln -s busybox ls 30 | $ ln -s busybox ps 31 | $ cd .. 32 | # mouting the proc virtual filesystem is required 33 | # to run the ps command 34 | $ sudo mount -t proc proc ./proc/ 35 | $ sudo chroot . sh 36 | ``` 37 | 38 | - we are now in a shell for which the root filesystem is `newroot`: 39 | 40 | ``` 41 | # ls / 42 | bin proc 43 | # ls /bin 44 | busybox ls ps sh 45 | ``` 46 | 47 | 48 | Note that we still have access to all the processes of the system: 49 | 50 | ``` 51 | # ps 52 | [...] 53 | ``` 54 | 55 | - If you open a new terminal and run a command: 56 | ``` 57 | $ sleep 10000 58 | ``` 59 | 60 | - then go back to your chroot environment and try to stop this process: 61 | ``` 62 | # ps | grep sleep 63 | 9550 1001 sleep 10000 64 | # kill 9550 65 | ``` 66 | 67 | - the process started outside of the chroot environment will stop: 68 | ``` 69 | $ sleep 10000 70 | Completed 71 | ``` 72 | 73 | ## Introduction 74 | 75 | The Pod is the master piece of the Kubernetes cluster architecture. 76 | 77 | The fundamental goal of Kubernetes is to help you manage your containers. The Pod is the minimal piece deployable in a Kubernetes cluster, containing one or several containers. 78 | 79 | From the `kubectl` command line, you can run a pod containing a container as simply as running this command: 80 | 81 | ```shell 82 | $ kubectl run --generator=run-pod/v1 nginx --image=nginx 83 | ``` 84 | 85 | By adding `--dry-run -o yaml` to the command, you can see the YAML template you would have to write to create the same Pod: 86 | 87 | ```shell 88 | $ kubectl run --generator=run-pod/v1 nginx --image=nginx --dry-run -o yaml 89 | apiVersion: v1 90 | kind: Pod 91 | metadata: 92 | creationTimestamp: null 93 | labels: 94 | run: nginx 95 | name: nginx 96 | spec: 97 | containers: 98 | - image: nginx 99 | name: nginx 100 | resources: {} 101 | dnsPolicy: ClusterFirst 102 | restartPolicy: Always 103 | status: {} 104 | ``` 105 | 106 | Or, if you extremely simplify the template: 107 | 108 | ```yaml 109 | -- simple.yaml 110 | apiVersion: v1 111 | kind: Pod 112 | metadata: 113 | name: nginx 114 | spec: 115 | containers: 116 | - name: nginx 117 | image: nginx 118 | ``` 119 | 120 | You can now start the Pod by using this template: 121 | ``` 122 | $ kubectl apply -f simple.yaml 123 | ``` 124 | 125 | Or, if you are a Go developer, you can use the `client-go` library to run the Pod (complete sources are on the `simple/` directory): 126 | 127 | ```go 128 | pod := corev1.Pod{ 129 | ObjectMeta: metav1.ObjectMeta{ 130 | Name: "nginx", 131 | }, 132 | Spec: corev1.PodSpec{ 133 | Containers: []corev1.Container{ 134 | { 135 | Name: "nginx", 136 | Image: "nginx", 137 | }, 138 | }, 139 | }, 140 | } 141 | 142 | podsClient := clientset.CoreV1().Pods("default") 143 | _, err := podsClient.Create(&pod) 144 | ``` 145 | 146 | In this introduction, we have seen three ways to create a Pod: 147 | - with `kubectl run` 148 | - with `kubectl apply` 149 | - with the `client-go` library. 150 | 151 | The Pod created is ready for production ... if you are not very fussy. Otherwise, the Pod offers a long list of parameters to make it more production-ready. We will examine in this document all these parameters. 152 | 153 | ## Pod specs 154 | 155 | Here is a classification of the Pod parameters. 156 | 157 | - **Containers** parameters will define and parameterize more precisely each container of the Pod, whether it is a normal container (`Containers`) or an init container (`InitContainers`). The `ImagePullSecrets` parameter will help to download containers images from private registries. 158 | 159 | - **Volumes** parameter (`Volumes`) will define a list of volumes that containers will be able to mount and share. 160 | 161 | - **Scheduling** parameters will help you define the most appropriate Node to deploy the Pod, by selecting nodes by labels (`NodeSelector`), directly specifying a node name (`NodeName`), 162 | using `Affinity` and `Tolerations`, by selecting a specific scheduler (`ScedulerName`), and by requiring a specific runtime class (`RuntimeClassName`). They will also be used to prioritize a Pod over other Pods (`PriorityClassName`and `Priority`). 163 | 164 | - **Lifecycle** parameters will help define if a Pod should restart after termination (`RestartPolicy`) and fine-tune the periods after which processes running in the containers of a terminating pod are killed (`TerminationGracePeriodSeconds`) or after which a running Pod will be stopped if not yet terminated (`ActiveDeadlineSeconds`). They also help define readiness of a pod (`ReadinessGates`). 165 | 166 | - **Hostname and Name resolution** parameters will help define the hostname (`Hostname`) and part of the FQDN (`Subdomain`) of the Pod, add hosts in the */etc/hosts* files of the containers (`HostAliases`), fine-tune the */etc/resolv.conf* files of the containers (`DNSConfig`) and define a policy for the DNS configuration (`DNSPolicy`). 167 | 168 | - **Host namespaces** parameters will help indicate if the Pod must use host namespaces for network (`HostNetwork`), PIDs (`HostPID`), IPC (`HostIPC`) and if containers will share the same (non-host) process namespace (`ShareProcessNamespace`). 169 | 170 | - **Service account** parameters will be useful to give specific rights to a Pod, by affecting it a specific service account (`ServiceAccountName`) or by disabling the automount of the default service account with `AutomountServiceAccountToken`. 171 | 172 | - **Security Context** parameter (`SecurityContext`) help define various security attributes and common container settings at the pod level. 173 | 174 | ## Container Specs 175 | 176 | The most important part of the definition of a Pod is the definition of the containers it will contain. 177 | 178 | We can separate container parameters in two parts. The first part are parameters that are related to the container runtime (image, entrypoint, ports, environment variables and volumes), the second part are parameters that will be handled by the Kubernetes system. 179 | 180 | The parameters related to container runtime are: 181 | 182 | - **Image** parameters define the image of the container (`Image`) and the policy to pull the image (`ImagePullPolicy`). 183 | 184 | - **Entrypoint** parameters define the command (`Command`) and arguments (`Args`) of the entrypoint and its working directory (`WorkingDir`). 185 | 186 | - **Ports** parameter (`Ports`) defines the list of ports to expose from the container. 187 | 188 | - **Environment variables** parameters help define the environment variables that will be exported in the container, 189 | either directly (`Env`) or by referencing ConfigMap or Secret values (`EnvFrom`). 190 | 191 | - **Volumes** parameters define the volumes to mount into the container, whether they are a filesystem volume (`VolumeMounts`) or a raw block volume (`VolumeDevices`). 192 | 193 | The parameters related to Kubernetes are: 194 | 195 | - **Resources** parameter (`Resources`) helps define the resource requirements and limits for a container. 196 | 197 | - **Lifecycle** parameters help define handlers on lifecycle events (`Lifecycle`), parameterize the termination message (`TerminationMessagePath` and `TerminationMessagePolicy`), and define probes to check liveness (`LivenessProbe`) and readiness (`ReadinessProbe`) of the container. 198 | 199 | - **Security Context** parameter help define various security attributes and common container settings at the container level. 200 | 201 | - **Debugging** parameters are very specialized parameters, mostly for debugging purposes (`Stdin`, `StdinOnce` and `TTY`). 202 | 203 | ## Pod Controllers 204 | 205 | The pod, although being the master piece of the Kubernetes architecture, is rarely used alone. You will generally use a Controller to run a pod with some specific policies. 206 | 207 | The different controllers handling pods are: 208 | 209 | - `ReplicaSet`: ensures that a specified number of pod replicas are running at any given time. 210 | - `Deployment`: enables declarative updates for Pods and ReplicaSets. 211 | - `StatefulSet`: manages updates of Pods and ReplicaSets taking care of stateful resources. 212 | - `DaemonSet`: ensures that all or some nodes are running a copy of a Pod. 213 | - `Job`: starts pods and ensures they complete. 214 | - `CronJob`: creates a Job on a time-based schedule. 215 | 216 | In Kubernetes, all controllers respect the principle of the **Reconcile Loop**: the controller perpetually **watches** for some objects of interest, to be able to detect if the actual state of the *world* (the objects running in the cluster) satisfies the specs of the different objects the controller is responsible for and to adapt the *world* consequently. 217 | 218 | ## ReplicaSet controller 219 | 220 | Parameters for a ReplicaSet are: 221 | - `Replicas` indicates how many replicas of selected Pods you want. 222 | - `Selector` defines the Pods you want the ReplicaSet controller to manage. 223 | - `Template` is the template used to create new Pods when insufficient replicas are detected by the Controller. 224 | - `MinReadySeconds` indicates the number of seconds the controller should wait after a Pod starts without failing to consider the Pod is ready. 225 | 226 | The ReplicaSet controller perpetually **watches** the Pods with the labels specified with `Selector`. At any given time, if the number of actual running Pods with these labels: 227 | - is greater than the requested `Replicas`, some Pods will be terminated to satisfy the number of replicas. Note that the terminated Pods are not necessarily Pods that were created by the ReplicaSet controller. 228 | - is lower than the requested `Replicas`, new Pods will be created with the specified Pod `Template` to satisfy the number of replicas. Note that to avoid the ReplicaSet controller to create Pods in a loop, the specified `Template` must create a Pod selectable by the specified `Selector`. 229 | 230 | Note that: 231 | - the `Selector` parameter of a ReplicaSet is immutable, 232 | - changing the `Template` of a ReplicaSet will not have an immediate effect. It will affect the Pods that will be created after this change, 233 | - changing the `Replicas` parameter will immediately trigger the creation or termination of Pods. 234 | 235 | ## Deployment controller 236 | 237 | Parameters for a `Deployment` are: 238 | - `Replicas` indicates the number of replicas requested. 239 | - `Selector` defines the Pods you want the Deployment controller to manage. 240 | - `Template` is the template requested for the Pods. 241 | - `MinReadySeconds` indicates the number of seconds the controller should wait after a Pod starts without failing to consider the Pod is ready. 242 | - `Strategy` 243 | - `RevisionHistoryLimit` 244 | - `Paused` 245 | - `ProgressDeadlineSeconds` 246 | 247 | The Deployment controller perpetually **watches** the ReplicaSets with the requested `Selector`. Among these: 248 | - if a ReplicaSet with the requested `Template` exists, the controller will ensure that the number of `Replicas` for this ReplicaSet equals the number of requested `Replicas` (by using the requested `Strategy`) and `MinReadySeconds` equals the requested one. 249 | - if no ReplicaSet exists with the requested `Template`, the controller will create a new ReplicaSet with the requested `Replicas`, `Selector`, `Template` and `MinReadySeconds`. 250 | - for ReplicaSets with a non matching `Template`, the controller will ensure that the number of `Replicas` is set to zero (by using the requested `Strategy`). 251 | 252 | Note that: 253 | - the `Selector` parameter of a Deployment is immutable, 254 | - changing the `Template` parameter of a Deployment will immediately: 255 | - either trigger the creation of a new ReplicaSet if no one exists with the requested `Selector` and `Template` 256 | - or update an existing one matching the requested `Selector` and `Template` with the requested `Replicas` (using `Strategy`), 257 | - set to zero the number of `Replicas` of other ReplicaSets, 258 | - changing the `Replicas` or `MinReadySeconds` parameter of a Deployment will immediately update the corresponding value of the corresponding ReplicaSet (the one with the requested `Template`). 259 | -------------------------------------------------------------------------------- /deployment/deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: nginx 5 | spec: 6 | replicas: 2 7 | selector: 8 | matchLabels: 9 | app: nginx 10 | template: 11 | metadata: 12 | labels: 13 | app: nginx 14 | spec: 15 | containers: 16 | - name: nginx 17 | image: nginx 18 | -------------------------------------------------------------------------------- /replicaset/replicaset.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: ReplicaSet 3 | metadata: 4 | name: nginx 5 | spec: 6 | replicas: 2 7 | selector: 8 | matchLabels: 9 | app: nginx 10 | template: 11 | metadata: 12 | labels: 13 | app: nginx 14 | spec: 15 | containers: 16 | - name: nginx 17 | image: nginx 18 | -------------------------------------------------------------------------------- /simple/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/feloy/aoap/simple-go 2 | 3 | go 1.12 4 | 5 | require ( 6 | github.com/gogo/protobuf v1.2.1 // indirect 7 | github.com/golang/protobuf v1.3.2 // indirect 8 | github.com/google/gofuzz v1.0.0 // indirect 9 | github.com/googleapis/gnostic v0.3.0 // indirect 10 | github.com/imdario/mergo v0.3.7 // indirect 11 | github.com/json-iterator/go v1.1.6 // indirect 12 | github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect 13 | github.com/modern-go/reflect2 v1.0.1 // indirect 14 | github.com/spf13/pflag v1.0.3 // indirect 15 | golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4 // indirect 16 | golang.org/x/net v0.0.0-20190628185345-da137c7871d7 // indirect 17 | golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 // indirect 18 | golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 // indirect 19 | gopkg.in/inf.v0 v0.9.1 // indirect 20 | gopkg.in/yaml.v2 v2.2.2 // indirect 21 | k8s.io/api v0.0.0-20190708174958-539a33f6e817 22 | k8s.io/apimachinery v0.0.0-20190704094733-8f6ac2502e51 23 | k8s.io/client-go v11.0.0+incompatible 24 | k8s.io/klog v0.3.3 // indirect 25 | k8s.io/utils v0.0.0-20190712204705-3dccf664f023 // indirect 26 | sigs.k8s.io/yaml v1.1.0 // indirect 27 | ) 28 | -------------------------------------------------------------------------------- /simple/go.sum: -------------------------------------------------------------------------------- 1 | cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= 2 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 3 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 4 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 5 | github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM= 6 | github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= 7 | github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= 8 | github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= 9 | github.com/gogo/protobuf v1.0.0 h1:2jyBKDKU/8v3v2xVR2PtiWQviFUyiaGk2rpfyFT8rTM= 10 | github.com/gogo/protobuf v1.0.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= 11 | github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE= 12 | github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= 13 | github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= 14 | github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= 15 | github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= 16 | github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 17 | github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs= 18 | github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 19 | github.com/google/btree v1.0.0 h1:0udJVsspx3VBr5FwtLhQQtuAsVc79tTq0ocGIPAU6qo= 20 | github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= 21 | github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 22 | github.com/google/gofuzz v1.0.0 h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw= 23 | github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= 24 | github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 25 | github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= 26 | github.com/googleapis/gnostic v0.3.0 h1:CcQijm0XKekKjP/YCz28LXVSpgguuB+nCxaSjCe09y0= 27 | github.com/googleapis/gnostic v0.3.0/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= 28 | github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 h1:+ngKgrYPPJrOjhax5N+uePQ0Fh1Z7PheYoUI/0nzkPA= 29 | github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= 30 | github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= 31 | github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= 32 | github.com/imdario/mergo v0.3.7 h1:Y+UAYTZ7gDEuOfhxKWy+dvb5dRQ6rJjFSdX2HZY1/gI= 33 | github.com/imdario/mergo v0.3.7/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= 34 | github.com/json-iterator/go v1.1.6 h1:MrUvLMLTMxbqFJ9kzlvat/rYZqZnW3u4wkLzWTaFwKs= 35 | github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= 36 | github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= 37 | github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= 38 | github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= 39 | github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= 40 | github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= 41 | github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= 42 | github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= 43 | github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI= 44 | github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= 45 | github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= 46 | github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= 47 | github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= 48 | github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= 49 | github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI= 50 | github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= 51 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 52 | github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= 53 | github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg= 54 | github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= 55 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 56 | github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= 57 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 58 | golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4 h1:HuIa8hRrWRSrqYzx1qI49NNxhdi2PrY7gxVSq1JjLDc= 59 | golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 60 | golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 61 | golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 62 | golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 63 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 64 | golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 65 | golang.org/x/net v0.0.0-20190628185345-da137c7871d7 h1:rTIdg5QFRR7XCaK4LCjBiPbx8j4DQRpdYMnGn/bJUEU= 66 | golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 67 | golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 h1:SVwTIAaPC2U/AvvLNZ2a7OVsmBpC8L5BlwK1whH3hm0= 68 | golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= 69 | golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 70 | golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 71 | golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 72 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 73 | golang.org/x/sys v0.0.0-20190412213103-97732733099d h1:+R4KGOnez64A81RvjARKc4UT5/tI9ujCIVX+P5KiHuI= 74 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 75 | golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f h1:25KHgbfyiSm6vwQLbM3zZIe1v9p/3ea4Rz+nnM5K/i4= 76 | golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 77 | golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= 78 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 79 | golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= 80 | golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= 81 | golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 h1:SvFZT6jyqRaOeXpc5h/JSfZenJ2O330aBsf7JfSUXmQ= 82 | golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= 83 | golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 84 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 85 | google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= 86 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 87 | gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 88 | gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= 89 | gopkg.in/inf.v0 v0.9.0 h1:3zYtXIO92bvsdS3ggAdA8Gb4Azj0YU+TVY1uGYNFA8o= 90 | gopkg.in/inf.v0 v0.9.0/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= 91 | gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= 92 | gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= 93 | gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= 94 | gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 95 | gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= 96 | gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 97 | k8s.io/api v0.0.0-20190708174958-539a33f6e817 h1:V6YPTc5fSnwv7EBjx6es9VyAki/6bqK4M3ECA6WwfBk= 98 | k8s.io/api v0.0.0-20190708174958-539a33f6e817/go.mod h1:iuAfoD4hCxJ8Onx9kaTIt30j7jUFS00AXQi6QMi99vA= 99 | k8s.io/api v0.0.0-20190712022805-31fe033ae6f9 h1:sbrvmfIQxEkFARFDPWY7DMwG+1cGcFwOzfACZbfFhY4= 100 | k8s.io/api v0.0.0-20190712022805-31fe033ae6f9/go.mod h1:quCKyJONbDKoYS6YlndaZ0BUdM1jU4J8fCiC0S2ctLI= 101 | k8s.io/apimachinery v0.0.0-20190704094733-8f6ac2502e51 h1:Nuz3yWD9v9dVvDiVSBIah+B+pxkxQxtuBAx2712t7tQ= 102 | k8s.io/apimachinery v0.0.0-20190704094733-8f6ac2502e51/go.mod h1:ccL7Eh7zubPUSh9A3USN90/OzHNSVN6zxzde07TDCL0= 103 | k8s.io/apimachinery v0.0.0-20190711222657-391ed67afa7b/go.mod h1:M2fZgZL9DbLfeJaPBCDqSqNsdsmLN+V29knYJnIXlMA= 104 | k8s.io/apimachinery v0.0.0-20190712095106-75ce4d1e60f1 h1:liWloDHcJ4ByTPt6eyXHcWnis3H8zmKdlJnIY2IjH+s= 105 | k8s.io/apimachinery v0.0.0-20190712095106-75ce4d1e60f1/go.mod h1:M2fZgZL9DbLfeJaPBCDqSqNsdsmLN+V29knYJnIXlMA= 106 | k8s.io/client-go v7.0.0+incompatible h1:kiH+Y6hn+pc78QS/mtBfMJAMIIaWevHi++JvOGEEQp4= 107 | k8s.io/client-go v7.0.0+incompatible/go.mod h1:7vJpHMYJwNQCWgzmNV+VYUl1zCObLyodBc8nIyt8L5s= 108 | k8s.io/client-go v8.0.0+incompatible h1:tTI4hRmb1DRMl4fG6Vclfdi6nTM82oIrTT7HfitmxC4= 109 | k8s.io/client-go v8.0.0+incompatible/go.mod h1:7vJpHMYJwNQCWgzmNV+VYUl1zCObLyodBc8nIyt8L5s= 110 | k8s.io/client-go v11.0.0+incompatible h1:LBbX2+lOwY9flffWlJM7f1Ct8V2SRNiMRDFeiwnJo9o= 111 | k8s.io/client-go v11.0.0+incompatible/go.mod h1:7vJpHMYJwNQCWgzmNV+VYUl1zCObLyodBc8nIyt8L5s= 112 | k8s.io/klog v0.3.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= 113 | k8s.io/klog v0.3.1 h1:RVgyDHY/kFKtLqh67NvEWIgkMneNoIrdkN0CxDSQc68= 114 | k8s.io/klog v0.3.1/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= 115 | k8s.io/klog v0.3.3 h1:niceAagH1tzskmaie/icWd7ci1wbG7Bf2c6YGcQv+3c= 116 | k8s.io/klog v0.3.3/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= 117 | k8s.io/kube-openapi v0.0.0-20190228160746-b3a7cee44a30/go.mod h1:BXM9ceUBTj2QnfH2MK1odQs778ajze1RxcmP6S8RVVc= 118 | k8s.io/utils v0.0.0-20190712204705-3dccf664f023 h1:1H4Jyzb0z2X0GfBMTwRjnt5ejffRHrGftUgJcV/ZfDc= 119 | k8s.io/utils v0.0.0-20190712204705-3dccf664f023/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew= 120 | sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs= 121 | sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= 122 | -------------------------------------------------------------------------------- /simple/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | "os" 6 | "path/filepath" 7 | 8 | corev1 "k8s.io/api/core/v1" 9 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 10 | "k8s.io/client-go/kubernetes" 11 | "k8s.io/client-go/tools/clientcmd" 12 | ) 13 | 14 | func main() { 15 | 16 | pod := corev1.Pod{ 17 | ObjectMeta: metav1.ObjectMeta{ 18 | Name: "nginx", 19 | }, 20 | Spec: corev1.PodSpec{ 21 | Containers: []corev1.Container{ 22 | { 23 | Name: "nginx", 24 | Image: "nginx", 25 | }, 26 | }, 27 | }, 28 | } 29 | 30 | clientset, err := getClientset() 31 | if err != nil { 32 | panic(err.Error()) 33 | } 34 | 35 | podsClient := clientset.CoreV1().Pods("default") 36 | _, err = podsClient.Create(&pod) 37 | if err != nil { 38 | panic(err.Error()) 39 | } 40 | } 41 | 42 | func getClientset() (*kubernetes.Clientset, error) { 43 | var kubeconfig *string 44 | if home := homeDir(); home != "" { 45 | kubeconfig = flag.String("kubeconfig", filepath.Join(home, ".kube", "config"), "(optional) absolute path to the kubeconfig file") 46 | } else { 47 | kubeconfig = flag.String("kubeconfig", "", "absolute path to the kubeconfig file") 48 | } 49 | flag.Parse() 50 | 51 | config, err := clientcmd.BuildConfigFromFlags("", *kubeconfig) 52 | if err != nil { 53 | panic(err.Error()) 54 | } 55 | 56 | return kubernetes.NewForConfig(config) 57 | } 58 | 59 | func homeDir() string { 60 | if h := os.Getenv("HOME"); h != "" { 61 | return h 62 | } 63 | return os.Getenv("USERPROFILE") // windows 64 | } 65 | -------------------------------------------------------------------------------- /simple/simple.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: nginx 5 | spec: 6 | containers: 7 | - name: nginx 8 | image: nginx 9 | --------------------------------------------------------------------------------