[MUSIC PLAYING]
MIKE COLEMAN: Hi, I'm Mike Coleman, a developer advocate
here at Google Cloud.
And in this video, I want to talk to you
about how you manage your applications after you've
migrated them using Migrate for Anthos.
[MUSIC PLAYING]
Getting your application containerized
is just the first step.
You'll also need to consider how you manage
that application going forward.
How do you handle base operating system
updates, application patching, and other Day Two tasks?
The rest of this video aims to answer some of those questions.
As a quick side note, I'm not going
to spend a lot of time talking about how container images are
constructed.
If you're not familiar with that topic, pause the video,
go check out the documentation on the Docker site
and come back and rejoin me.
Also, if you're not familiar with Migrate for Anthos,
check out our earlier videos where
we provide an overview of the service
as well as how to perform an actual migration.
You can find a link to those in the description below.
With that being said, let's take a look
at how Migrate for Anthos creates the container image
from a migrated application.
Migrate for Anthos automatically examines a source VM
and extracts the workloads running there
into their own container images.
When looking at the ongoing management of those containers,
it's important to understand how their images are actually
built.
The container that you run in production
is a combination of two intermediate images.
The first one is the Migrate for Anthos runtime layer
and the other is what we refer to as the non-runnable system
layer.
The non-runnable system layer contains the extracted portion
of your migrated workloads and will
serve as the base for all future updates.
As the name implies, this layer by itself doesn't do anything.
It's only by combining it with the Migrate for Anthos
runtime layer that you get a container image that you
can deploy into production.
So let's look at the Dockerfile so you can
see how this works in practice.
Now, the Dockerfile uses a multi-stage
build to combine the two artifacts together.
This first FROM statement tells Docker to use the Migrate
for Anthos 1.6.0 runtime image from the Google Container
Registry, and to refer to it going forward
as, quote-unquote, "migrate-for-anthos-runtime."
The next FROM tells the Docker file
to use the image that was generated
when you ran your migration.
It's also stored up in the Google Container Registry
under your project.
Notice that Docker will refer to this image as, quote unquote,
"source-content."
As an aside, while I am specifically
using Google Container Registry in this example,
depending on where you're migrating from,
we can also use AWS' Elastic Container
Registry or a local registry.
This section is where you would run any updates,
and we're going to cover that in more
detail in the next section.
So for now, we'll just skip over it.
This line tells Docker to copy the file system starting
at the root from the migrate-for-anthos-runtime
into the container image.
Now, remember that the container image we're copying into
is the source-content image.
So basically, this command copies the runtime container
image into the source-content image.
And the last line tells the container
to run the v2k.go script and start
your migrated application.
Now, as I've said, this Dockerfile
is what's used to create the migrated application
configuration that you initially deploy after running Migrate
for Anthos.
But what do you do if, down the road,
you need to update the image for some reason?
For example, you need to install an updated dependency
or patch your application or upgrade the underlying
Migrate for Anthos runtime.
Going back to our Dockerfile-- now,
updating the migrate-for-anthos-runtime is
actually pretty simple.
You just go back to that first FROM line
and you update the version.
If you need to update any part of your application,
including system or language libraries
or the application code itself, you
would do that after the second FROM statement.
So, for instance, if I'm a node developer,
I might copy in a new package.json
and run "npm install" to update some
of the packages my application is using.
Or I could copy in a new app.js file
to update my actual application code.
The underlying file system in the container
is the same as what you had in your VM,
so you would just update the files
in their original locations.
Now, from here, you could manually
run docker build to create an updated image,
push that to GCR, and then roll out
the new version of your application.
But manually building the new container images
could become tedious if you are regularly processing updates.
A better approach is to use a tool like Cloud Build
to automate the process with a modern CI/CD pipeline.
By leveraging a tool like Cloud Build,
you can define triggers such that whenever
a change is pushed to your source code repository,
a new container image is created.
And once that new image is created,
you can perform manual or automated tests.
And then finally, using either manual or automated processes,
you can push that code out into production.
Let's take a look at how we would implement
a pipeline in practice.
I'm going to construct a simple pipeline that
will connect to my GitHub repo such
that when I push a new change to GitHub,
a new container image will be pushed up to GCR.
From there I'll update my Kubernetes YAML
and roll that updated app into production.
OK, so let's go ahead here.
We're going to start in Cloud Build,
and I want to show you the trigger that I built earlier.
Remember, a trigger is something that can kick off
via different processes.
So we have a trigger here that when
I push to a branch in my GitHub repo
here to do a Cloud Build where I've installed the GitHub
app for Cloud Build.
When I hit the master branch with an update,
it's going to go ahead and run a Dockerfile,
and it's going to do that in the root of the repository,
looking for a file called Dockerfile,
and it's going to build us a new image that
is tagged with the short SHA of the build process, right?
So that'll be our unique tag.
And then if we look down here below,
what we can see is the actual Dockerfile build-- er,
the docker build command where we're going to build that
and we're going to point to that Dockerfile
that I just mentioned.
So that's what's going to happen whenever
I push a change to my repo.
Now, this is the Dockerfile.
We talked about this earlier in the video.
You can see here is the runtime.
Here is the non-runnable base that
is created as part of the migration process.
And then what I have added to it, if we come down here,
is I'm basically saying, copy the contents of this repo
into /usr/src/todo in the container, right,
in the container image.
And that's where it was located in the VM.
That's where it was-- the code was located
in the container, as well then.
They're the same.
So now what I want to do is I want to come up
and I want to actually go ahead and make a change to my source
code.
So I'm going to come up here into this showTasks file
here at the top, and I'm going to click here.
And I'm going to go in-- and I'm not running these on VMs,
so it's not a host.
It's actually a pod.
So let me change this to pod, and then I
will save this file out.
And then I will move down here into the terminal
and I'll do a git add * to add the change file.
I'll commit that to the repo with a commit message
of "update host string."
And then I'll go ahead and do a push.
Now, this push will kick off that trigger
that we just talked about.
So if I come into history, you can see it's already building.
So we'll come in here and I'll show you here
in a second when this comes up.
You can actually see there's that commit message
I used, "update host string."
This is going to take a bit, so let me pause the video
and I'll rejoin you when it's done.
OK, so we've finished up here.
And if we come down, we can see there's
where we copied the source code into the image, as I mentioned.
And here's that short SHA and we're
going to use that to do the update to our application.
So let's go to the image repository here--
Container Registry.
Look at the images.
And that's where the non-runnable base gets stored
by the migration process.
And there's the todo directory.
That is where we actually get our deployable applications.
So there's the one we just created.
And now we're going to deploy that
by opening up a Cloud Shell and editing the Kubernetes YAML
file.
So let's open this up and we're going to move
into the directory where the artifacts are stored,
and we're going to edit the deployment_spec.yaml
and we're just going to scroll down here,
and we're going to change that tag on the image name
to the one we just created.
We're going to save that out.
And then we're going to go into the terminal,
and we're going to go ahead and--
well, before we do that, let me point this out.
So it says "served by host."
That's what we're going to change.
So now let me go here and I want to go ahead and clear
the screen.
And then we'll do a kubectl apply -f deployment_spec.yaml,
and that's going to update the statefulset with the new image.
Let's do a get pods with a watch so we can watch that happen.
And while that's happening, I want to just talk
about a couple of things.
One, this is not exactly what you would do, right?
There would be a step between building the image
and deploying it, and that would involve some sort of testing.
We talked about that.
And the other thing is you could automate this step
if you wanted to, right?
In the video, we don't really have time
to go through that process, but you could fully automate this
so you automate your testing.
You automate the sign-offs and the release,
and then you automate the push to production.
Here we're just basically automating the building
of the container image.
We're assuming a manual test step and a manual deployment
step.
All right, so we're almost done here.
The containers should be up and running
in just a couple of seconds.
And looks like it's just about done.
So let's go and check on that application
and see if our change got reflected.
So we'll come up here, click on todo list app,
and you can see down here, actually there it is.
It's now served by a pod instead of a host.
So the application has been updated.
So in this video, we talked about how
you can use a Cloud Build build trigger connected to a GitHub
repo to automate the creation or the updating
of your migrated applications.
That about wraps it up for this video.
I hope you found it useful.
If you want more information on Migrate for Anthos,
we have some additional videos posted here on YouTube,
so check those out and then head on over
to cloud.google.com/migrate/anthos
to learn more.
[MUSIC PLAYING]