Hello, Habr readers! Kubernetes is one of the key components of the modern cloud ecosystem. This technology provides reliability, scalability, and resilience for container virtualization. John Arundel and Justin Domingus discuss the Kubernetes ecosystem and introduce proven solutions to everyday problems. Step by step, you'll build your own cloud-oriented application and create the infrastructure to support it, set up a development environment, and a continuous deployment pipeline that will be useful when working on future applications.
• Start working with containers and Kubernetes from scratch: no special experience is required to learn the topic. • Launch your own clusters or choose a managed Kubernetes service from Amazon, Google, etc. • Use Kubernetes to manage the lifecycle of containers and resource consumption. • Optimize clusters based on cost, performance, resilience, power, and scalability. • Explore the best tools for developing, testing, and deploying your applications. • Utilize current industry practices for ensuring security and control. • Implement DevOps principles in your company so that development teams can operate more flexibly, quickly, and effectively.
Who the book is for
The book is especially relevant for staff in administration departments responsible for servers, applications, and services, as well as for developers involved in building new cloud services or migrating existing applications to Kubernetes and the cloud. Don't worry, there's no need to know how to work with Kubernetes and containers—we will teach you everything.
Experienced Kubernetes users will also find much of value here: topics such as RBAC, continuous deployment, managing sensitive data, and observability are discussed in depth. We hope that within the pages of this book, there will be something interesting for you regardless of your skills and experience.
What questions does the book answer?
During the planning and writing of this book, we discussed cloud technologies and Kubernetes with hundreds of people, engaging with both industry leaders and experts as well as complete newcomers. Below are specific questions for which they would like to see answers in this publication.
- "I’m curious why I should spend time on this technology. What problems will it help solve for me and my team?"
- "Kubernetes seems interesting, but it has quite a high entry threshold. Creating a simple example is not difficult, but further administration and debugging can be daunting. We would like reliable advice on how people manage Kubernetes clusters in real-world situations and what challenges we are likely to face."
- "It would be helpful to have subjective advice. The Kubernetes ecosystem offers too many options for beginner teams to choose from. When the same task can be accomplished in multiple ways, how do you determine which is best? How do you make a choice?"
And perhaps the most important question of all:
- "How can I use Kubernetes without disrupting my business?"
Excerpt. Configuration and Secret Objects
The ability to separate the application logic of Kubernetes from its configuration (that is, from any values or settings that may change over time) is very valuable. Configuration values typically include parameters intended for specific environments, DNS addresses of external services, and authentication credentials.
Of course, all this can be hardcoded directly into the code, but such an approach is not flexible enough. For example, to change a configuration value, you would then have to rebuild and redeploy your code. A much better solution would be to separate the configuration from the code and read it from a file or environment variables.
Kubernetes provides several different ways to manage configuration. Firstly, you can pass values to the application via environment variables specified in the pod spec (see the "Environment Variables" section on p. 192). Secondly, configuration data can be stored directly in Kubernetes using ConfigMap and Secret objects.
In this chapter, we will explore these objects in detail and examine some practical approaches to managing configuration and sensitive data using a demonstration application as an example.
Updating pod wrappers upon configuration changes
Imagine that your cluster has a deployment and you want to change some values in its ConfigMap. If you are using a Helm chart (see the section "Helm: Package Manager for Kubernetes" on p. 102), you can automatically detect the configuration change and restart your pod wrappers using a clever trick. Add the following annotation to your deployment specification:
checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") .
| sha256sum }}Now the deployment template includes a checksum of the configuration parameters: when the parameters change, the checksum will update. If you run the helm upgrade command, Helm will detect that the deployment specification has changed and will restart all pod wrappers.
Sensitive Data in Kubernetes
We already know that the ConfigMap object provides a flexible mechanism for storing and accessing configuration data in the cluster. However, most applications have information that is secret and confidential: for example, passwords or API keys. While it can be stored in ConfigMap, this solution is not ideal.
Instead, Kubernetes offers a special type of object designed for storing sensitive data: Secret. Let's look at an example of how this object can be applied in our demonstration application.
First, take a look at the Kubernetes manifest for the Secret object (see hello-secret-env/k8s/secret.yaml):
apiVersion: v1
kind: Secret
metadata:
name: demo-secret
stringData:
magicWord: xyzzy
In this example, the secret key magicWord has a value of xyzzy (en.wikipedia.org/wiki/Xyzzy_(computing)). The word xyzzy is actually very useful in the computer world. Similar to ConfigMap, you can store multiple key-value pairs in a Secret object. For simplicity, we are using just one "key-value" pair here.
Using Secret Objects as Environment Variables
Like ConfigMap, a Secret object can be made available to a container as environment variables or as a file on its disk. In the following example, we will assign a value from the Secret to an environment variable:
spec:
containers:
- name: demo
image: cloudnatived/demo:hello-secret-env
ports:
- containerPort: 8888
env:
- name: GREETING
valueFrom:
secretKeyRef:
name: demo-secret
key: magicWordRun the following command in the demo repository to apply the manifests:
kubectl apply -f hello-secret-env/k8s/
deployment.extensions "demo" configured
secret "demo-secret" createdAs before, forward the local port to the deployment to see the result in your browser:
kubectl port-forward deploy/demo 9999:8888
Forwarding from 127.0.0.1:9999 -> 8888
Forwarding from [::1]:9999 -> 8888When you open the address :9999/ you should see the following:
The magic word is "xyzzy"
Writing Secret objects to files
In this example, we will connect a Secret object to a container as a file. The code is located in the hello-secret-file folder of the demo repository.
To connect the Secret as a file, we will use the following deployment:
spec:
containers:
- name: demo
image: cloudnatived/demo:hello-secret-file
ports:
- containerPort: 8888
volumeMounts:
- name: demo-secret-volume
mountPath: "/secrets/"
readOnly: true
volumes:
- name: demo-secret-volume
secret:
secretName: demo-secretAs in the section "Creating configuration files from ConfigMap objects" on p. 240, we create a volume (in this case, it is demo-secret-volume) and attach it to the container in the volumeMounts specification section. The mountPath field is set to /secrets, so Kubernetes will create one file for each "key-value" pair defined in the Secret object in this folder.
In our example, we have defined only one "key-value" pair named magicWord, so the manifest will create one file /secrets/magicWord in the container with confidential data, available read-only.
If you apply this manifest in the same way as in the previous example, you should get the same result:
The magic word is "xyzzy"
Reading Secret objects
In the previous section, we used the kubectl describe command to output the contents of ConfigMap. Can we do the same with Secret?
kubectl describe secret/demo-secret
Name: demo-secret
Namespace: default
Labels:
Annotations:
Type: Opaque
Data
====
magicWord: 5 bytesNote that the data itself is not displayed. Secret objects in Kubernetes are of type Opaque: this means their contents are not shown in the output of kubectl describe, logs, and terminal, which makes it impossible to accidentally expose confidential information.
To view the encoded version of sensitive data in YAML format, use the command kubectl get:
kubectl get secret/demo-secret -o yaml
apiVersion: v1
data:
magicWord: eHl6enk=
kind: Secret
metadata:
...
type: Opaquebase64
What is eHl6enk=, it doesn't resemble our original value at all? In fact, this is a Secret object represented in base64 encoding. Base64 is a scheme for encoding arbitrary binary data into a string of characters.
Since sensitive information can be binary and unavailable for output (as is the case with a TLS encryption key), Secret objects are always stored in base64 format.
The text beHl6enk= is our secret word xyzzy encoded in base64. This can be confirmed by executing the command base64 --decode in the terminal:
echo "eHl6enk=" | base64 --decode
xyzzyThus, while Kubernetes protects you from accidentally outputting sensitive data in the terminal or log files, if you have read permissions for Secret objects in a certain namespace, this data can be retrieved in base64 format and subsequently decoded.
If you need to encode some text in base64 (for example, to place it in a Secret), use the base64 command without arguments:
echo xyzzy | base64
eHl6enkKAccessing Secret objects
Who can read and edit Secret objects? This is determined by RBAC — the access control mechanism (we will discuss it in detail in the subsection 'Introduction to Role-Based Access Control' on p. 258). If you are using a cluster where RBAC is absent or not enabled, all your Secret objects are accessible to any users and containers (later, we will explain that you should not have any production cluster without RBAC).
Passive data encryption
What about those who have access to the etcd database where Kubernetes stores all its information? Can they read sensitive data without having read permissions for Secret objects via the API?
Starting from version 1.7, Kubernetes supports passive encryption of data. This means that sensitive information within etcd is stored on disk in an encrypted form and cannot be read even by those who have direct access to the database. A key is required for decryption, which is only available to the Kubernetes API server. In a properly configured cluster, passive encryption should be enabled.
You can check whether passive encryption is working in your cluster as follows:
kubectl describe pod -n kube-system -l component=kube-apiserver |grep encryption
--experimental-encryption-provider-config=...If you do not see the experimental-encryption-provider-config flag, passive encryption is not enabled. When using Google Kubernetes Engine or other managed Kubernetes services, your data is encrypted using a different mechanism, so the flag will be absent. Check with your Kubernetes provider whether the contents of etcd are encrypted.
Storing sensitive data
There are certain Kubernetes resources that should never be deleted from the cluster, such as particularly important Secret objects. You can prevent a resource from being deleted using an annotation provided by the Helm manager:
kind: Secret
metadata:
annotations:
"helm.sh/resource-policy": keepStrategies for managing Secret objects
In the example from the previous section, sensitive data was protected from unauthorized access immediately after being saved in the cluster. However, in the manifest files, they were stored as plain text.
You should never place sensitive information in files that are in version control. So how can you safely administer and store such information before applying it to the Kubernetes cluster?
You can choose any tools or strategies to work with sensitive data in your applications, but you will still need to answer at least the following questions.
- Where to store sensitive data so that it is highly available?
- How to make sensitive data accessible to your active applications?
- What should happen to your applications when you replace or edit sensitive data?
About the Authors
John Arundel is a consultant with 30 years of experience in the computer industry. He has authored several books and collaborates with many companies from different countries, advising them on cloud-oriented infrastructure and Kubernetes. In his free time, he enjoys surfing, has decent skills in pistol shooting, and plays the piano as a hobby. He lives in a fairy-tale cottage in Cornwall, England.
Justin Domingus is a systems administration engineer working in a DevOps environment with Kubernetes and cloud technologies. He enjoys spending time outdoors, drinking coffee, catching crabs, and sitting at the computer. He lives in Seattle, Washington, with his wonderful cat and even more wonderful wife and best friend, Adrienne.
» Learn more about the book at
»
»
For Habr users, a 25% discount with the coupon — Kubernetes
Upon payment for the print version of the book, an electronic version will be sent to your email.
Source: habr.com
