minor corrections

This commit is contained in:
tomas f
2021-08-12 11:35:06 -03:00
parent e60dd32f36
commit 9e791ec9cc
6 changed files with 46 additions and 37 deletions

View File

@@ -24,6 +24,7 @@ all: book
book: pdf ebook
ebook: epub mobi
docx: $(BUILD)/docx/$(BOOKNAME).docx
pdf: $(BUILD)/pdf/$(BOOKNAME).pdf
epub: $(BUILD)/epub/$(BOOKNAME).epub
mobi: $(BUILD)/mobi/$(BOOKNAME).mobi
@@ -33,6 +34,10 @@ html: $(BUILD)/html/$(BOOKNAME).html
clean:
rm -r $(BUILD)
$(BUILD)/docx/$(BOOKNAME).docx: $(TITLE) $(CHAPTERS)
mkdir -p $(BUILD)/docx
docker run --rm $(EXTRA_OPTS) --volume `pwd`:/data pandoc/latex:2.6 -f markdown-implicit_figures -H make-code-small.tex -V geometry:margin=1.5in -o /data/$@ $^
$(BUILD)/pdf/$(BOOKNAME).pdf: $(TITLE) $(CHAPTERS)
mkdir -p $(BUILD)/pdf
docker run --rm $(EXTRA_OPTS) --volume `pwd`:/data pandoc/latex:2.6 -f markdown-implicit_figures -H make-code-small.tex -V geometry:margin=1.5in -o /data/$@ $^

View File

@@ -2,7 +2,7 @@
# 2 Deploying to Kubernetes
When getting started with Kubernetes, one of the first commands that you learn and use is generally `kubectl run`. Folks who have experience with Docker tend to compare it to `docker run` and think: "Ah, this is how I can simply run a container!"
When getting started with Kubernetes, one of the first commands you learn and use is generally `kubectl run`. Folks who have experience with Docker tend to compare it to `docker run` and think: "Ah, this is how I can simply run a container!"
As it turns out, when you use Kubernetes, you don't simply run a container.
@@ -77,7 +77,7 @@ $ kubectl create deployment web --image=nginx
deployment.apps/web created
```
The bottom line is that we should always use the most explicit command available in order to future proof our deployments.
The bottom line is that we should always use the most explicit command available to future-proof our deployments.
Next, you'll learn the roles of these different objects and how they are essential to zero-downtime deployments in Kubernetes.
@@ -654,3 +654,4 @@ The end result is a higher development velocity, lower time-to-market
for fixes and new features, as well as better availability of your
applications. Which is the whole point of implementing containers
in the first place.

View File

@@ -1,12 +1,12 @@
\newpage
# 3 CI/CD Best Practices for Cloud Native Applications
# 3 CI/CD Best Practices for Cloud-Native Applications
Engineering leaders strive to deliver bug-free products to customers as productively as possible. Todays cloud-native technology empowers teams to iterate, at scale, faster than ever. But to experience the promised agility, we need to change how we deliver software.
“CI/CD” stands for the combined practices of Continuous Integration (CI) and Continuous Delivery (CD). It is a timeless way of developing software in which youre able to release updates at any time in a sustainable way. When changing code is routine, development cycles are faster. Work is more fulfilling. Companies can improve their products many times per day and delight their customers.
In this chapter, well review the principles of CI/CD and see how we can apply them to developing cloud native applications.
In this chapter, well review the principles of CI/CD and see how we can apply them to developing cloud-native applications.
## 3.1 What Makes a Good CI/CD Pipeline
@@ -28,7 +28,7 @@ For this to happen, the CI/CD tool of choice should fit into the existing develo
A reliable pipeline always produces the same output for a given input. And with consistent runtime. Intermittent failures cause intense frustration among developers.
Engineers like to do things on their own, and often they opt to maintain their CI/CD system. But operating CI/CD that provides on-demand, clean, stable, and fast resources is a complicated job. What seems to work well for one project or a few developers usually breaks down later. The team and the number of projects grow the technology stack changes. Then someone from management realizes that by delegating that task, the team could spend more time on the actual product. At that point, if not earlier, the engineering team moves from a self-hosted to a cloud-based CI/CD solution.
Engineers like to do things independently, and they often opt to maintain their CI/CD system. But operating CI/CD that provides on-demand, clean, stable, and fast resources is a complicated job. What seems to work well for one project or a few developers usually breaks down later. The team and the number of projects grow the technology stack changes. Then someone from management realizes that by delegating that task, the team could spend more time on the actual product. At that point, if not earlier, the engineering team moves from a self-hosted to a cloud-based CI/CD solution.
### 3.1.3 Completeness
@@ -297,3 +297,4 @@ Chapter 1 includes a roadmap for adopting Docker for this purpose. Chapter 2 des
[^jez]: What is Proper Continuous Integration, Semaphore
[https://semaphoreci.com/blog/2017/03/02/what-is-proper-continuous-integration.html](https://semaphoreci.com/blog/2017/03/02/what-is-proper-continuous-integration.html?utm_source=ebook&utm_medium=pdf&utm_campaign=cicd-docker-kubernetes-semaphore)

View File

@@ -16,7 +16,7 @@ Our process will include the following steps:
- **Canary deploy**: Deploy the image as a canary to a fraction of the users.
- **Run functional tests**: Verify the canary in production to decide if we should go ahead.
- **Run functional tests**: Verify the canary in production to decide if we should proceed.
- **Deploy**: If the canary passes the test, deploy the image to all users.
@@ -24,7 +24,7 @@ Our process will include the following steps:
## 4.1 Docker and Kubernetes Commands
In previous chapters weve learned most of the Docker and Kubernetes commands that well need in this chapter. Here are a few that we havent seen yet.
In previous chapters, weve learned most of the Docker and Kubernetes commands that well need in this chapter. Here are a few that we havent seen yet.
### 4.1.1 Docker Commands
@@ -38,7 +38,7 @@ A Docker *registry* stores Docker images. Docker CLI provides the following comm
- `tag`: renames an image or changes its tag.
- `exec`: starts a process in an already-running container. Compare it with `docker run` which starts a new container instead.
- `exec`: starts a process in an already-running container. Compare it with `docker run`, which creates a new container instead.
### 4.1.2 Kubectl Commands
@@ -66,7 +66,7 @@ Its time to put the book down and get our hands busy for a few minutes. In th
### 4.2.1 Install Prerequisites
Youll need to the following tools installed on your computer:
Youll need to have the following tools installed on your computer:
- **git** (_[https://git-scm.com](https://git-scm.com)_) to manage the code.
@@ -280,9 +280,9 @@ In this process, we'll use Semaphores built-in Docker registry. This is faste
### 4.3.2 CD Pipelines: Canary and Stable Deployments
In chapter 3, we have talked about Continuous Delivery and Continuous Deployment. In chapter 2, we learned about canaries and rolling deployments. Our CI/CD workflow combines these two practices.
In chapter 2, we learned about canaries and rolling deployments. In chapter 3, we have talked about Continuous Delivery and Continuous Deployment. Our CI/CD workflow combines these two practices.
A canary deployment is a limited release of a new version. Well call it _canary release_, and the previous version that is still used by a majority of users the _stable release_.
A canary deployment is a limited release of a new version. Well call it _canary release_, and the previous version still used by most users is the _stable release_.
We can do a canary deployment by connecting the canary pods to the same load balancer as the rest of the pods. As a result, a set fraction of user traffic goes to the canary. For example, if we have nine stable pods and one canary pod, 10% of the users would get the canary release.
@@ -303,6 +303,7 @@ Imagine that this is your initial state: you have three pods running version **v
When you deploy **v2** as a canary, you scale down the number of **v1** pods to 2, to keep the total amount of pods to 3.
Then, you can start a rolling update to version **v2** on the stable deployment. One at a time, all its pods are updated and restarted, until they are all running on **v2** and you can get rid of the canary.
Then, you can start a rolling update to version **v2** on the stable deployment. One at a time, all its pods are updated and restarted until they are all running on **v2**, and you can get rid of the canary.
![Completing a stable release](./figures/05-transition-stable.png){ width=95% }

View File

@@ -1,4 +1,3 @@
\newpage
## 4.4 Implementing a CI/CD Pipeline With Semaphore
@@ -9,15 +8,15 @@ In this section, well learn about Semaphore and how to use it to build cloud-
For a long time, developers looking for a CI/CD tool had to choose between power and ease of use.
On one hand, there was Jenkins which can do just about anything, but is difficult to use and requires dedicated ops teams to configure, maintain and scale.
On the one hand, there was Jenkins, which can do just about anything but is challenging to use and requires dedicated ops teams to configure, maintain and scale.
On the other hand, there were several hosted services that let developers just push their code and not worry about the rest of the process. However, these services are usually limited to running simple build and test steps, and would often fall short in need of more elaborate continuous delivery workflows, which is often the case with containers.
On the other hand, several hosted services let developers push their code and not worry about the rest of the process. However, these services are usually limited to running simple build and test steps. They would often fall short and need more elaborate continuous delivery workflows, which is often the case with containers.
Semaphore (_[https://semaphoreci.com](https://semaphoreci.com/?utm_source=ebook&utm_medium=pdf&utm_campaign=cicd-docker-kubernetes-semaphore)_) started as one of the simple hosted CI services, but eventually evolved to support custom continuous delivery pipelines with containers, while retaining a way of being easy to use by any developer, not just dedicated ops teams. As such, it removes all technical barriers to adopting continuous delivery at scale:
- It's a cloud-based service that scales on demand. There's no software for you to install and maintain.
- It's a cloud-based service that scales on-demand. There's no software for you to install and maintain.
- It provides a visual interface to model custom CI/CD workflows quickly.
- It's the fastest CI/CD service, due to being based on dedicated hardware instead of common cloud computing services.
- It's the fastest CI/CD service due to being based on dedicated hardware instead of common cloud computing services.
- It's free for open source and small private projects.
The key benefit of using Semaphore is increased team productivity. Since there is no need to hire supporting staff or expensive infrastructure, and it runs CI/CD workflows faster than any other solution, companies that adopt Semaphore report a very large, 41x ROI comparing to their previous solution [^roi].
@@ -33,12 +32,12 @@ To get started with Semaphore:
- Go to _[https://semaphoreci.com](https://semaphoreci.com?utm_source=ebook&utm_medium=pdf&utm_campaign=cicd-docker-kubernetes-semaphore)_ and click to sign up with your GitHub account.
- GitHub will ask you to let Semaphore access your profile information. Allow this so that Semaphore can create an account for you.
- Semaphore will walk you through the process of creating an organization. Since software development is a team sport, all Semaphore projects belong to an organization. Your organization will have its own domain, for example, `awesomecode.semaphoreci.com`.
- Semaphore will ask you to choose between a time-limited free trial with unlimited capacity, a free plan, and an open-source plan. This chapter will demonstrate a workflow using Semaphore's Docker Registry, which is available within a free trial or a paid account. However you can easily replace it with a free public registry like Docker Hub and implement the same workflow with an open source account.
- Semaphore will ask you to choose between a time-limited free trial with unlimited capacity, a free plan, and an open-source plan. This chapter will demonstrate a workflow using Semaphore's Docker Registry, available within a free trial or a paid account. However, you can easily replace it with a free public registry like Docker Hub and implement the same workflow with an open-source account.
- Finally, you'll be greeted with a quick product tour.
### 4.4.3 Creating a Semaphore Project For The Demo Repository
We assume that you have previously forked the demo project from _[https://github.com/semaphoreci-demos/semaphore-demo-cicd-kubernetes](https://github.com/semaphoreci-demos/semaphore-demo-cicd-kubernetes)_ to your GitHub account.
We assume you have previously forked the demo project from _[https://github.com/semaphoreci-demos/semaphore-demo-cicd-kubernetes](https://github.com/semaphoreci-demos/semaphore-demo-cicd-kubernetes)_ to your GitHub account.
On Semaphore, click on *New Project* at the top of the screen. Then, click on *Choose a repository*. Next, Semaphore will present you a list of repositories to choose from as the source of your project:
@@ -50,7 +49,7 @@ Semaphore will quickly initialize the project. Behind the scenes, it will set up
The next screen lets you invite collaborators to your project. Semaphore mirrors access permissions of GitHub, so if you add some people to the GitHub repository later, you can "sync" them inside project settings on Semaphore.
Click on *Continue to Workflow Setup*. Semaphore will ask you if you want to use the existing pipelines or create one from scratch. At this point, you can choose to use the existing configuration to get directly to the final workflow. In this chapter, however, we want to learn how to create the pipelines so well make a fresh start.
Click on *Continue to Workflow Setup*. Semaphore will ask you if you want to use the existing pipelines or create one from scratch. At this point, you can choose to use the current configuration to get directly to the final workflow. In this chapter, however, we want to learn how to create the pipelines so well make a fresh start.
![Start from scratch or use existing pipeline](./figures/05-sem-existing-pipeline.png){ width=95% }
@@ -62,7 +61,7 @@ To make the process of creating projects easier, Semaphore provides starter work
![Choosing a starter workflow](./figures/05-sem-starter-workflow.png){ width=95% }
Semaphore will immediately start the workflow. Wait a few seconds and your first Docker image is ready, congratulations!
Semaphore will immediately start the workflow. Wait a few seconds, and your first Docker image is ready. Congratulations!
![Starter run](./figures/05-sem-starter-run.png){ width=95% }
@@ -92,7 +91,7 @@ Blocks and jobs define what to do at each step. Jobs define the commands that do
Jobs inherit their configuration from their parent block. All the jobs in a block run in parallel, each in its isolated environment. If any of the jobs fails, the pipeline stops with an error.
Blocks run sequentially, once all the jobs in the block complete, the next block starts.
Blocks run sequentially. Once all the jobs in the block are complete, the next one starts.
### 4.4.5 The Continous Integration Pipeline
@@ -102,7 +101,7 @@ At this point, you should be seeing the Workflow Builder with the Docker Build s
![Build block](./figures/05-sem-build-block.png){ width=95% }
Each line on the job is a command to execute. The first command in the job is `checkout`, which is a built-in script that clones the repository at the correct revision[^sem-toolbox]. The next command, `docker build`, builds the image using our `Dockerfile`.
Each line on the job is a command to execute. The first command in the job is `checkout`, which is a built-in script that clones the repository at the correct revision[^sem-toolbox]. The following command, `docker build`, builds the image using our `Dockerfile`.
[^sem-toolbox]: You can find the complete Semaphore toolbox at [https://docs.semaphoreci.com/reference/toolbox-reference](https://docs.semaphoreci.com/reference/toolbox-reference/?utm_source=ebook&utm_medium=pdf&utm_campaign=cicd-docker-kubernetes-semaphore)
@@ -137,9 +136,9 @@ Each command has its purpose:
4. Builds a newer version of the image using the latest code.
5. Pushes the new image to the registry.
The perceptive reader will note that we introduced special environment variables; these come predefined in every job[^environment]. The variables starting with `SEMAPHORE_REGISTRY_*` are used to access the private registry. Also, were using `SEMAPHORE_WORKFLOW_ID`, which is guaranteed to be unique for each run, to tag the image.
The discerning reader will note that we introduced special environment variables; these come predefined in every job[^environment]. The variables starting with `SEMAPHORE_REGISTRY_*` are used to access the private registry. Also, were using `SEMAPHORE_WORKFLOW_ID`, which is guaranteed to be unique for each run, to tag the image.
[^docker-registry]: Semaphore's built-in Docker registry is available under a paid plan or free trial. If you're using a free or open source plan, use an external service like Docker Hub instead. The pipeline will be slower but the workflow will be the same.
[^docker-registry]: Semaphore's built-in Docker registry is available under a paid plan or free trial. If you're using a free or open-source plan, use an external service like Docker Hub instead. The pipeline will be slower, but the workflow will be the same.
[^environment]: The full environment reference can be found at [https://docs.semaphoreci.com/ci-cd-environment/environment-variables](https://docs.semaphoreci.com/ci-cd-environment/environment-variables/?utm_source=ebook&utm_medium=pdf&utm_campaign=cicd-docker-kubernetes-semaphore)
![Build block](./figures/05-sem-build-block-2.png){ width=95% }
@@ -178,7 +177,7 @@ docker run -it \
npm run lint
```
Next, click on the *+Add another job* link below the job to create a new one called “Functional test”. Type these commands:
Next, click on the *+Add another job* link below to create a new one called “Functional test”. Type these commands:
``` bash
sem-service start postgres
@@ -192,9 +191,9 @@ docker run --net=host -it \
npm run migrate
```
This job tests two things: that the container connects to the database (`ping`) and that it can create the tables (`migrate`). Obviously, well need a database for this to work; fortunately, we have `sem-service`, which lets us start database engines like MySQL, Postgres, or MongoDB with a single command[^sem-service].
This job tests two things: that the container connects to the database (`ping`) and can create the tables (`migrate`). Obviously, well need a database for this to work; fortunately, we have `sem-service`, which lets us start database engines like MySQL, Postgres, or MongoDB with a single command[^sem-service].
[^sem-service]: For the complete list of services sem-service can manage check: [https://docs.semaphoreci.com/ci-cd-environment/sem-service-managing-databases-and-services-on-linux/](https://docs.semaphoreci.com/ci-cd-environment/sem-service-managing-databases-and-services-on-linux/?utm_source=ebook&utm_medium=pdf&utm_campaign=cicd-docker-kubernetes-semaphore)
[^sem-service]: For the complete list of services, sem-service can manage check: [https://docs.semaphoreci.com/ci-cd-environment/sem-service-managing-databases-and-services-on-linux/](https://docs.semaphoreci.com/ci-cd-environment/sem-service-managing-databases-and-services-on-linux/?utm_source=ebook&utm_medium=pdf&utm_campaign=cicd-docker-kubernetes-semaphore)
Finally, add a third job called “Integration test” and type these commands:
@@ -206,7 +205,7 @@ docker run --net=host -it \
npm run test
```
This last test runs the code in `src/database.test.js`, which checks if the application can write and delete rows in the database.
This last test runs the code in `src/database.test.js`, checking if the application can write and delete rows in the database.
![Test block](./figures/05-sem-test-block.png){ width=80% }
@@ -234,11 +233,12 @@ This completes the setup of the CI pipeline.
### 4.4.6 Your First Build
Weve covered a lot of things in a few pages; here, we have the chance to pause for a little bit and try the CI pipeline. Click on the *Run the workflow* button on the top-right corner and then click on *Start*.
Weve covered many things in a few pages; here, we have the chance to pause for a little bit and try the CI pipeline. Click on the *Run the workflow* button on the top-right corner and click on *Start*.
![Run this workflow](./figures/05-sem-run-workflow.png){ width=80% }
After a few seconds the pipeline will start building and testing the container.
After a few seconds, the pipeline will start building and testing the container.
![CI pipeline done](./figures/05-sem-ci-pipeline.png){ width=95% }

View File

@@ -4,7 +4,7 @@
In this book we will show you how to deploy to Kubernetes hosted on three public cloud providers: Amazon AWS, Google Cloud Platform, and DigitalOcean. With small modifications, the process will work with any other cloud or Kubernetes instance.
This book will show you how to deploy to Kubernetes hosted on three public cloud providers: Amazon AWS, Google Cloud Platform, and DigitalOcean. With slight modifications, the process will work with any other cloud or Kubernetes instance.
Well deploy the application in a three-node Kubernetes cluster. You can pick a different size based on your needs, but youll need at least three nodes to run an effective canary deployment with rolling updates.
@@ -17,7 +17,7 @@ To create the Kubernetes cluster:
- Sign up or log in to your account on [digitalocean.com](https://www.digitalocean.com).
- Create a *New Project*.
- Create a *Kubernetes* cluster: select the latest version and choose one of the available regions. Name your cluster “semaphore-demo-cicd-kubernetes”.
- While DigitalOcean is working on the cluster, go to *API* menu and generate a *Personal Access Token* with Read & Write permissions.
- While DigitalOcean is working on the cluster, go to the *API* menu and generate a *Personal Access Token* with Read & Write permissions.
Next, create a Container Registry with the following actions:
@@ -59,7 +59,7 @@ On Semaphore, create a secret for your Google Cloud Access Key file:
AWS calls its service *Elastic Kubernetes Service* (EKS). The Docker private registry is called *Elastic Container Registry* (ECR).
Creating a cluster on AWS is, unequivocally, a complex affair. So complex that there is a specialized tool for it:
Creating a cluster on AWS is, unequivocally, a complex affair. So tough that there is a specialized tool for it:
- Sign up or log in to your AWS account at [aws.amazon.com](https://aws.amazon.com).
- Select one of the available regions.
@@ -134,7 +134,7 @@ Once the cloud database is running:
- Create a PostgreSQL database (choose Standard Create) and call it “demo”. Type in a secure password for the `postgres` account.
- Select one of the available *templates*. The dev/test option is perfect for demoing the application. Under *Connectivity* select all the VPCs and subnets where the cluster is running (they should have appeared in eksctls output).
- In Availability Zone, select the same region the Kubernetes cluster is running.
- Under *Connectivity & Security* take note of the endpoint address
- Under *Connectivity & Security*, take note of the endpoint address
and port.
### 4.6.4 Creating the Database Secret on Semaphore
@@ -147,9 +147,10 @@ The database secret is the same for all clouds. Create a secret to store the dat
4. Add the following variables:
- `DB_HOST` with the database hostname or private IP.
- `DB_PORT` points to the database port (default is 5432).
- `DB_SCHEMA` for AWS should be called “postgres”, for the other clouds its value should be “demo”.
- `DB_SCHEMA` for AWS should be called “postgres”. For the other clouds, its value should be “demo”.
- `DB_USER` for the database user.
- `DB_PASSWORD` with the password.
- `DB_SSL` should be “true” for DigitalOcean, it can be left empty for the rest.
- `DB_SSL` should be “true” for DigitalOcean. It can be left empty for the rest.
5. Click on *Save Secret*.