Laravel on Kubernetes: Missing Migrations
60sAddresses a common pain point for developers deploying Laravel apps on Kubernetes, sparking engagement.
▶ Play ClipThis episode of Rawkode Live, hosted by Rawkode with guest Alex Burris, dives into deploying a Laravel application on Kubernetes with production-grade features. They cover database migrations, queue workers, scheduled tasks, secrets management, and rolling updates, using a simple example application to demonstrate each concept.
Alex introduces himself as a lead developer at ShopBlox, an e-commerce platform using Laravel, and explains they will cover topics not yet addressed in previous episodes.
The example application includes jobs, email sending, queue tasks, scheduled tasks, and asset compilation, designed to test infrastructure components.
They deploy MariaDB on Kubernetes using a simple Deployment and Service, setting environment variables for the database user and password.
They create a ConfigMap for environment variables and a Secret for the app key, explaining the difference and best practices for secrets management.
They use an init container to run `php artisan migrate --force` before the main application starts, ensuring migrations run once per deployment.
They create a CronJob to run `php artisan schedule:run` every minute, replacing traditional cron for Laravel's scheduler.
They deploy queue workers as a separate Deployment running `php artisan queue:work`, allowing independent scaling and resource management.
They demonstrate a rolling update by changing the image tag and applying the deployment, showing how Kubernetes handles zero-downtime updates.
"The title accurately reflects the content, which focuses on deploying a Laravel application to Kubernetes with production considerations."
How do you run database migrations in a Kubernetes deployment?
Use an init container that runs `php artisan migrate --force`.
61:25
How do you handle Laravel's scheduled tasks in Kubernetes?
Use a CronJob resource that runs `php artisan schedule:run` every minute.
70:40
How do you deploy Laravel queue workers in Kubernetes?
Use a Deployment with the command `php artisan queue:work`.
75:00
What Kubernetes resources are used to manage environment configuration?
Use ConfigMaps for non-sensitive data and Secrets for sensitive data.
35:13
What tools can encrypt secrets before storing them in version control?
Use tools like Mozilla SOPS, Sealed Secrets, or the Kapitan project.
58:27
What deployment strategy does Kubernetes use by default for zero-downtime updates?
Use a rolling update strategy, which is the default for Deployments.
84:05
What do `maxSurge` and `maxUnavailable` parameters control in a rolling update?
`maxSurge` controls how many extra pods can be created during an update, and `maxUnavailable` controls how many can be unavailable.
84:17
How do you configure Kubernetes to use a locally built Docker image?
Set the image pull policy to `Never`.
20:54
How do you configure Laravel to log to standard output instead of a file?
Set the `LOG_CHANNEL` environment variable to `stdout` or `stderr`.
44:28
What Kubernetes volume type is recommended for temporary storage like logs and cache?
Use emptyDir volumes for ephemeral storage like logs and cache.
25:07
Init Containers for Migrations
Shows a clean, Kubernetes-native way to run database migrations before the main application starts.
61:25CronJob for Scheduled Tasks
Demonstrates how to replace traditional cron with Kubernetes CronJob for Laravel's scheduler.
70:40Queue Workers as Deployments
Explains why queue workers should be separate Deployments for scalability and resource management.
75:00Secrets Management Tools
Provides practical recommendations for encrypting secrets in version control.
58:27Rolling Update Defaults
Clarifies that Kubernetes Deployments use rolling updates by default for zero-downtime deployments.
84:05[00:15] you
[00:29] [Music]
[00:42] my
[00:48] hey hello and welcome to today's episode
[00:51] of rockwood live i am your host rock
[00:53] hood
[00:54] today we're diving back into our laravel
[00:57] on kubernetes journey
[00:59] and i am joined by a previous guest
[01:02] friend
[01:02] and budding conference joiner beer
[01:05] drinker
[01:06] alex burris hey how are you i'm good
[01:09] thank you
[01:10] i'm all right actually i'm doing quite
[01:12] well i'm excited to
[01:13] come back to my my lanravel stuff here
[01:15] and and see what we're doing
[01:17] like um we've done
[01:20] well sorry i i think i've done five or
[01:22] six episodes on this now you joined us
[01:24] for one of those
[01:25] and you reached out and said there's
[01:27] still a few things that we haven't
[01:28] covered yet do you want to give us
[01:30] well first just a little introduction
[01:32] about yourself and then we'll talk about
[01:34] what we want to try and cover today
[01:37] yeah sure so um i'm alex i am a
[01:41] lead developer at a e-commerce platform
[01:43] in the uk called shopblox
[01:44] um we use laravel um a lot
[01:48] and we're working towards moving into
[01:50] kubernetes and docker alongside some of
[01:52] our previous infrastructure
[01:54] stuff using council um and that's
[01:56] basically why i reached out because
[01:58] some of the previous streams have
[02:01] some topics which model operation or
[02:05] haven't been covered yet so hopefully we
[02:08] can cover those today
[02:09] and anything else today soon i've got a
[02:11] full list of um
[02:13] a full list of stuff to cover on the
[02:15] post and they're here so
[02:16] we'll see where we get to in it but
[02:18] there's quite a few things in there
[02:19] we'll certainly try and cross
[02:21] a few of them off and i'm always more
[02:23] than happy to schedule
[02:24] more of these if we want in the future
[02:26] and i really want to make sure that we
[02:27] cover
[02:28] everything that teams like yours need to
[02:31] get their laravel application running on
[02:33] kubernetes successfully so we'll do our
[02:36] best
[02:37] um all right why don't we talk a little
[02:41] bit about what you're prepared so we're
[02:43] not using like a real production grade
[02:45] application today right you've put
[02:46] something together that is going to be
[02:48] is it close to that is it going to use
[02:50] the components that are missing last
[02:52] time
[02:52] give us a little flavor on that yeah so
[02:55] what i've created is
[02:57] not something anybody would ever use in
[02:58] production it's got two main points
[03:02] one of them creates some jobs and one of
[03:05] them
[03:05] is a um sends an email the email that
[03:08] says hello world
[03:09] like it's very minimalist but it adds
[03:12] things to the queue
[03:13] um it has some scheduled tasks in the
[03:15] background
[03:16] it does some um
[03:19] it has some assets which can be compiled
[03:22] and uh
[03:23] just things like that which every team
[03:25] will have none of them will be as basic
[03:26] as this
[03:27] but if you get the infrastructure down
[03:28] to run a scheduled task
[03:31] it doesn't matter what the task is if
[03:33] you've got uh stuff in the background to
[03:34] run
[03:35] queues it doesn't matter what the queue
[03:36] job is so we've just got some simple
[03:38] code here
[03:41] all right sweet let me just pull up the
[03:45] the repository so it's on github.com
[03:48] username alexbevers laravel dash example
[03:52] dash project
[03:54] um i already have this client
[03:58] here um we have a live share configured
[04:02] so i should see yep there's your name
[04:04] there so we're now in a position where
[04:06] we can try to address some of those
[04:07] concerns and that we're missing do you
[04:09] want to just quickly
[04:10] run through that list you've got and
[04:12] then we'll try and decide what is best
[04:13] to kick things off with
[04:15] yeah so um one of the things that's
[04:18] probably best to start with i guess is
[04:19] migrations
[04:20] literally every application i can ever
[04:21] think of requires migrations to run
[04:23] and you've touched this briefly in the
[04:25] past sharing well not sure about seeing
[04:27] how it would be done and i think the
[04:29] example still had
[04:30] like abc as like the
[04:33] um into the uh into the worker
[04:37] so that's that's probably the main one
[04:40] there's um
[04:41] the two big things beyond that i guess
[04:42] is queued jobs and
[04:44] scheduled jobs so on a normal server you
[04:47] would run
[04:48] supervisor and you'd have several
[04:51] different workers
[04:52] scheduled to run in the background to
[04:54] run a specific command called
[04:56] artisan um key work
[04:59] obviously it isn't going to be exactly
[05:01] the same as that in kubernetes so
[05:03] the but it'll be similar i assume and
[05:06] then there's also scheduled tasks which
[05:08] normally you'd use a current job for
[05:10] on your server that's i believe
[05:13] um there's like a scheduled tasks built
[05:15] into kubernetes so i assume that's how
[05:16] we've managed that as well
[05:18] but those are the three main things i'd
[05:19] say which
[05:21] most applications would make use of at
[05:23] some point
[05:26] um beyond that there's i've got things
[05:28] like
[05:29] um managing your secrets um so we've got
[05:32] uv
[05:32] stuff how that could be released and
[05:35] using config map that's
[05:36] less likely to be an issue because you
[05:38] can just inject it in the docker file
[05:40] and sorry in your docker image um
[05:44] then there's also things like asset
[05:45] deployment which you've covered in the
[05:46] past so that's less of an issue
[05:50] all right yeah there there's a fair
[05:52] amount there let's let's just see what
[05:53] we can get through it and then if we
[05:55] need to schedule more time we will
[05:56] definitely
[05:57] do that and tick it all um i think
[06:00] because you've gone through the effort
[06:02] to produce this application
[06:04] what we're trying to do is i'll just try
[06:05] and send as many pull requests as i can
[06:07] to it
[06:08] during this episode as we kind of work
[06:10] through this together
[06:12] and anything else we'll just try and
[06:13] make this the default example for
[06:15] kubernetes on marvel or laravel on
[06:17] kubernetes actually
[06:19] all right so let's see
[06:22] database migrations first then let's see
[06:24] what you've got in place for actually
[06:25] running this on kubernetes in fact i
[06:27] i don't have any kubernetes right now
[06:29] hold on let me start docker
[06:32] uh okay so we do have a docker compose
[06:36] fail
[06:37] uh that is a default one that comes with
[06:39] laravel i've not touched that whatsoever
[06:41] that's a development environment only i
[06:42] think
[06:43] something new that came with global fact
[06:48] i sent a pull request to the laravel
[06:49] project
[06:51] three or four years ago with a docker
[06:52] file and they said sorry we don't want
[06:54] to support docker
[06:55] just there you go just throw that out
[06:57] there i'm not better
[06:58] just saying now they now have like a
[07:02] first-party
[07:03] product called vapor which is to
[07:07] deploy onto aws lambda and so i assume
[07:09] that's pushed much more
[07:11] on the um getting docker working because
[07:14] they now make money from it so
[07:17] all right well i'm just clicking the
[07:19] magic reset
[07:21] kubernetes because i can't remember the
[07:22] last thing i was doing but that's to be
[07:24] fair so that's now reset and we'll
[07:25] wait for that to become healthy let's
[07:29] see
[07:30] the docker compose file that is not
[07:32] anything i've touched on i've not done
[07:34] anything
[07:34] for development all i've done is create
[07:36] two docker files which are inside
[07:38] resources ops
[07:39] docker um i've got two in there i've got
[07:43] an
[07:43] nginx one and one fpm one
[07:47] um those are the files which i've
[07:50] started okay well i mean this
[07:54] this won't work by default unless we use
[07:57] sale
[07:58] um
[07:58] [Music]
[08:03] i don't actually see a docker file here
[08:05] am i being silly
[08:06] um so inside it's inside of the vendor
[08:10] um so when you do computer install
[08:12] you'll get a
[08:14] vendor file uh a vendor folder which has
[08:16] laravel sale in there and that has
[08:18] different
[08:18] times you can specify which one and it
[08:20] will compile it based on that
[08:23] all right let's the half composer
[08:26] i don't uh all right
[08:29] um i don't believe that you would
[08:31] require a large sale for this that would
[08:33] just be for development environment only
[08:36] um you're right i'm going to get
[08:40] sidetracked there i was going to start
[08:41] putting together a development
[08:42] environment for this and to be honest
[08:44] i think that's what you can come up with
[08:47] yeah i i
[08:47] i don't think it's important i'm just
[08:49] going to create a docker file we just
[08:50] want an image with this application in
[08:52] it
[08:52] that's that's fine i'm going to use
[08:55] if you've done it it creates a docker
[08:56] file which will
[08:59] build and pm in the nginx image
[09:02] separately
[09:03] where are those resources ops
[09:10] yeah is this based on prior art from the
[09:13] other episodes
[09:14] exactly a copy of the previous streams
[09:17] all right okay good so we talked about
[09:19] i separated them out into two separate
[09:21] rather than having the
[09:22] make file specify individual targets
[09:25] i've made it so that
[09:26] they are just two separate two separate
[09:29] jobs because the overlap was very
[09:31] minimal
[09:32] so i think that's a good or bad idea but
[09:36] all right and you've already added make
[09:37] target that this is already
[09:39] my favorite episode ever because you've
[09:41] done all the work okay
[09:43] let's build these then so i'll just
[09:46] make sure i've got the target names
[09:48] we'll do build let's build fpm
[09:50] first and then we'll do build engine x
[09:56] okay so that's going to give us our two
[09:57] images which
[09:59] you know for anyone that's watching go
[10:02] watch the previous episodes we'll add
[10:03] the links into the description
[10:05] afterwards
[10:06] it walks you through the entire process
[10:07] we're going to assume
[10:09] that we're starting from the point where
[10:11] you've already built your fpm nginx
[10:12] images and pushed them to some container
[10:14] registry and we're going to try and get
[10:16] this working on kubernetes with
[10:18] all the bells and whistles that we've
[10:19] omitted previously
[10:21] um are you going to be doing this on
[10:23] kubernetes locally i assume are you
[10:24] going to be doing this on
[10:25] a production cloud environment
[10:30] i'm just going to use docker for mac
[10:31] unless you feel there's a reason we
[10:33] would need to have an
[10:34] alternative cluster but i don't think
[10:37] the only thing that i would say
[10:39] purely because i don't know much about
[10:40] it locally is external load balancers
[10:42] and how those sort of things work
[10:44] but that can be covered in a far later
[10:45] episode anyway
[10:47] yeah i have i have done previous
[10:49] episodes on ingress and advancing on
[10:51] kubernetes
[10:52] that aren't they're not larval specific
[10:53] and i don't think they have to be
[10:55] [Music]
[10:57] um
[10:59] that's that'll be all right i mean we
[11:01] can talk a little bit about how the
[11:03] the services and the angers work
[11:04] together but i don't think
[11:06] um i i don't need a cloud environment to
[11:08] kind of show that off
[11:10] yeah i don't think there's anything else
[11:13] that i could think of that is massively
[11:16] different
[11:17] from development or local environment
[11:22] all right well it looks like we do have
[11:24] a little bit of time to kill while this
[11:25] builds maybe i should have kicked that
[11:27] off
[11:27] previously however if anyone watching
[11:29] has any questions that they want us to
[11:31] address feel free to drop that in the
[11:32] comments
[11:33] or drop me a tweet
[11:36] at raw code so
[11:40] let me try and understand the migration
[11:43] path here so we're going to be using the
[11:45] artisan command
[11:47] which i don't think is ever important in
[11:49] here we went through this previously
[11:50] yeah
[11:51] which has to run a db migrate is that
[11:54] correct php migraines
[11:58] so does that i i need a database
[12:00] deployed to my kubernetes cluster then
[12:02] right
[12:02] uh yes i've not touched anything to do
[12:04] that yet all right
[12:05] sweet finally something i can do okay um
[12:09] that
[12:10] i've tested this locally with mysql
[12:12] shouldn't make any difference because
[12:13] it's all
[12:14] using the orm but yeah all right what
[12:16] database do you want
[12:18] uh let's go manually well movie dvd 10
[12:22] or whatever
[12:25] all right so i'm assuming you don't
[12:27] really need me to go through
[12:28] the production deployment mechanisms for
[12:30] murray db we're happy just to use
[12:32] something that's
[12:33] mariadb on kubernetes right yeah yeah
[12:36] but personally for me i avoid running
[12:38] any databases myself anyway i'd just
[12:40] rather use managed services
[12:42] save so much effort and um
[12:45] but some people i guess will be running
[12:48] images
[12:49] well for anyone that is going hey i
[12:51] wanna know how to do it under production
[12:52] just use helm go and use the you're
[12:55] gonna use work from other people there's
[12:57] a helm chart says the artifact hub let's
[12:59] talk about that actually so
[13:02] artifact hub this is from the cncf it
[13:06] hosts all of the
[13:07] cncf project artifacts go figure helm is
[13:10] one of those
[13:11] where we can just say hey give me
[13:12] mariadb we could filter it on helm
[13:15] charts if we wanted
[13:17] we click this and everything you need to
[13:19] know to get a
[13:20] pretty production grade deployment or
[13:22] maybe is going to be here you can use
[13:23] helm
[13:24] you tweak the values based on whatever
[13:25] you need and you deploy it
[13:27] um probably what i would recommend
[13:30] however for today
[13:31] i'm not going to do that just because i
[13:35] just want something quick
[13:36] what i am going to do is check the
[13:38] [Music]
[13:40] environment bars that i need i know i
[13:41] need to set the mysql root password
[13:43] maybe a user movement database
[13:44] i also want to make sure i got the
[13:45] version right so it looks like running
[13:47] 10 is okay
[13:48] and if i just search for my
[13:52] sql password
[13:55] these are the variables that i have
[13:57] available to configure this image
[14:00] and i'm going to drop these n so we're
[14:02] just going to say environment
[14:04] i'll get some space let's do
[14:08] uh mysql
[14:11] i'm pretty sure there's a random root
[14:15] not get too fancy today
[14:17] [Music]
[14:19] okay let's set a user and uh we'll set a
[14:22] value of
[14:23] laravel and we'll set the password
[14:31] laravel um
[14:34] horse no we don't need the host uh
[14:38] database yeah
[14:49] uh we'll just call it laravel was that
[14:51] standard is that what you would do in
[14:52] your application would you tweak it more
[14:53] than that
[14:54] um so i would personally name the
[14:58] database something relevant but
[14:59] obviously this
[15:00] is yeah i think this is relevant except
[15:04] is yeah fine all right okay cool
[15:07] and happily that is also the default
[15:09] that we have in the inv
[15:10] file oh is it uh
[15:13] yeah the name and password for different
[15:16] but
[15:17] that's easy to change all right okay
[15:20] uh let's deploy this oh no we need to
[15:24] expose this okay so
[15:26] uh one of the things we want to do is
[15:28] when we apply this deployment to
[15:30] kubernetes it's going to create the pods
[15:32] that run mario db followers
[15:33] we're going to by default the replicas
[15:35] will be one but we'll make that a bit
[15:37] more explicit so we're going to run one
[15:38] of these
[15:40] however what we want to do is
[15:43] make sure we can have service discovery
[15:46] around
[15:47] this pod which could be pods so that we
[15:50] can use dns to actually speak to it
[15:52] so i'm going to add a service
[15:56] of ready b
[15:59] uh the selector has to match what we
[16:02] have above
[16:03] so you can see app mirror db matches the
[16:05] same labels we applied to the deployment
[16:08] uh we don't need the target port because
[16:10] this is a pretty simple setup we're just
[16:12] going to say
[16:13] port 306 so that should be
[16:16] oh yeah good those are built as well
[16:18] which is handy
[16:19] so let's deploy uh was it resources
[16:24] ops uh kubernetes murray do we
[16:34] let's check my cluster
[16:37] oh there we go too many clusters
[16:43] and we should be able to run get pods
[16:46] oh we have an error i broke it um
[16:50] because i never set a random root
[16:51] password and i never said root password
[16:55] yeah that's the one i want it just means
[16:58] that
[16:58] i won't actually know the root password
[17:00] which i think is good so value
[17:05] what do you do then you go into the
[17:06] secrets to extract it
[17:08] or well we already have this user with
[17:10] this database configured
[17:12] so we're making sure that that's the
[17:14] root password right yeah
[17:15] yeah it's just the root password
[17:18] we can just apply that over the top
[17:20] we'll run a get pods watch
[17:22] we can already see that we have one
[17:23] mirror db running the error one is now
[17:26] terminating
[17:27] and that is good all right database
[17:31] do we require anything else
[17:36] um what's the q processing
[17:40] first of all why do we use them for the
[17:42] queue
[17:43] so the queue can just by default use
[17:46] mysql
[17:47] um you can use redis you can use
[17:50] um like wrap mq and all that sort of
[17:52] stuff but by default you can just make
[17:54] it one
[17:55] using the database so i'm just going to
[17:58] assume that that's the
[17:59] essential way of doing it um okay
[18:03] uh and this deployment that we have here
[18:07] uh let's see
[18:10] uh replicas one label
[18:18] that is complaining because i am not
[18:20] setting the resources required
[18:23] and so it's telling me that i could have
[18:25] stray pods i think
[18:29] oh no let's see
[18:32] resource limits yeah okay so
[18:40] there we go so we can minimize that to a
[18:41] single line yeah my
[18:43] my editor is just like you put and you
[18:45] know in production you don't want to
[18:47] deploy things without resource damage
[18:48] you don't want them to just start
[18:49] consuming
[18:50] all the cpu and memory across your
[18:52] cluster so you would say
[18:53] constrain nest is something that i
[18:55] consider to be safe
[18:57] is that a container or is that uh
[19:00] noodle yeah per container so i mean if
[19:02] we look at this as an example right you
[19:04] know we've got engine x here which
[19:07] really requires nothing um so we can say
[19:10] that the limits on this
[19:13] uh cpu
[19:18] now completes only going to get me so
[19:19] far say 500
[19:22] mm nginx probably isn't going to require
[19:26] too much uh as
[19:29] i'm going to kill whether it wants
[19:34] no memory limit i did that very limited
[19:38] is it memorize it memory
[19:41] you're correct cool thanks man
[19:45] so we can set that there and then fpm is
[19:47] probably going to require more so i
[19:48] think what we'll do just
[19:49] for the for fun let's just actually set
[19:52] these really
[19:53] low and we'll see them crash we'll try
[19:56] and boost them if we need
[19:57] we'll see what happens let's apply
[20:01] this so we're just going to apply our
[20:02] deployment i don't
[20:04] oh what have i got wrong
[20:14] uh hard to pick at the editor here it
[20:17] seems to be complaining
[20:24] okay my limits can't be unmarshaled
[20:27] quantities must match the regular
[20:28] expression
[20:32] uh okay so it doesn't want mib i think
[20:34] it just wants a m
[20:39] you thought it might be on two places of
[20:42] course i do
[20:43] thanks okay
[20:47] now we can run get pods
[20:50] kind of expect that to fail well we've
[20:52] got an image pull policy problem
[20:54] and you've got this set to always this
[20:55] is a local cluster
[20:57] and so we actually want this to be never
[21:01] because the image doesn't exist on a
[21:03] remote repository a remote registry
[21:06] okay so we can just apply that over the
[21:08] top
[21:10] and so what the way image pro policy
[21:12] works
[21:13] is that you know uh it actually seems
[21:16] quite healthy with those
[21:17] figures so we'll leave it for now but i
[21:18] do expect that to crash before the end
[21:19] of the episode
[21:20] when we tried winning anything yeah yeah
[21:23] so
[21:24] you had the image pulls policy to always
[21:26] and there are times and places where you
[21:28] want to use always definitely
[21:30] however when you have an image like this
[21:32] that
[21:33] let's talk about how this is resolved by
[21:35] kubernetes first when you do not provide
[21:37] a host for the registry
[21:40] this assumes that your image is
[21:45] this
[21:49] it assumes that you're an official image
[21:51] on the docker registry this is a
[21:52] hangover from when
[21:53] docker was pretty much the de facto
[21:56] container runtime
[21:57] and that it assumed you were always
[21:58] going to pull from the docker hub
[22:01] and that doesn't exist so when you have
[22:02] an image pull policy that's always in
[22:04] your cluster the controllers are going
[22:05] to reach out and try to get the latest
[22:07] hash
[22:07] or for that image it doesn't exist it
[22:10] fails and it exits
[22:12] so for local images what you actually
[22:13] need to do is the image pro policy never
[22:15] and just make sure it's available on the
[22:16] host
[22:18] and it's running and it's happy however
[22:21] our application probably isn't going to
[22:23] work first we haven't done those
[22:25] database migrations that we actually
[22:26] want to be doing and secondly it doesn't
[22:29] know where mariadb is yeah but if you
[22:32] try and access it you should
[22:34] i assume get error pages using in the
[22:37] lava lava page yeah i i would assume so
[22:40] for sure
[22:42] so let's port forward is this port 80
[22:45] no yeah yeah okay
[22:48] yeah it is okay uh so we'll make that
[22:50] available in port 8080 locally
[22:54] and we'll browse to there
[22:58] all right well our first problem is that
[23:00] we need somewhere to store our logs
[23:02] and we're getting a permission denied on
[23:05] that
[23:06] let's take a look at what's going on
[23:12] so i'm going to jump inside of this part
[23:15] i hope we've got access to bash
[23:19] oh it's an alpine one not mine okay so
[23:21] we have access to that
[23:27] i didn't look in the dock for fail where
[23:30] well i think
[23:38] yeah that's their application uh no
[23:40] that's missing most of it
[23:43] that's this is engine xl right are you
[23:46] in the engineering oh sorry for your
[23:48] knee
[23:50] yeah how's this deployed
[23:55] oh the names are quite for both uh
[23:59] yeah i didn't know whether or not
[24:00] calling something just like fpm was a
[24:02] good idea so i went
[24:04] okay here is our application we are
[24:07] actually the root user so that
[24:08] um directory failure here storage logs
[24:12] i'm assuming storage doesn't exist
[24:14] oh it doesn't um no storage exists by
[24:16] default
[24:22] ah well the engine x is running as www
[24:25] data they're inter
[24:27] oh sorry dm php fpm
[24:32] uh let's see ah of course right
[24:36] uh so obviously it's a good idea to
[24:39] run containers there's root uh well
[24:42] there is a little bit of juggling that
[24:44] has to be done with fail system
[24:46] permissions
[24:48] so let's let's see the best way to
[24:51] handle
[24:52] this is to provide
[24:55] temporary or ephemeral storage for
[24:58] things like that where we can control
[25:00] the volume that we want to make
[25:01] available
[25:03] so let's do uh
[25:07] okay so we can add a volume to our spec
[25:11] and let's call this logs
[25:15] i think it's a name logs
[25:19] and we want a empty dir
[25:25] i don't think that needs any
[25:26] configuration size limit medium me up we
[25:29] can just
[25:33] oh i can't remember when in doubt look
[25:36] at that kubernetes empty there
[25:39] um please seem to remember about empty
[25:41] div if there's anything that does wipe
[25:43] it out as well
[25:44] is that correct or is that well yeah
[25:45] we're just using it for cache okay it's
[25:47] not
[25:48] it's empty object so for logs and cache
[25:51] yeah i'm totally okay with that plus to
[25:53] be honest we're actually going to remove
[25:55] your logging to not be to a file and
[25:57] we're going to move that to standard out
[25:58] so that's maybe something we could do
[26:00] first however
[26:01] let's let's try and do it this way so we
[26:03] can show it working
[26:05] um and then we'll we'll change it up a
[26:09] little bit
[26:09] so we now have this volume available so
[26:12] empty
[26:12] just means create an empty volume
[26:14] ephemeral when a container or pod dies
[26:17] get rid of it that's it now we want to
[26:20] provide logging for our fpm
[26:22] so we're going to come in here and we're
[26:23] going to see if we have not volume
[26:25] devices it's volume mounts
[26:28] um we're going to have logs
[26:34] uh we want a mount path of w
[26:38] html storage
[26:41] logs and we don't need any other flags
[26:45] now this name here just has to match
[26:46] what we have here which
[26:47] does mount it to this location
[26:52] there is a way to configure
[26:55] the emptor um permissions via the
[26:58] security context
[27:00] let's see if we can pull that out our
[27:02] fingers
[27:04] so we can set um let's see if i can find
[27:08] this
[27:11] [Music]
[27:17] all right well let's try that in a
[27:18] second let's see what we have first
[27:20] because tomorrow i can't remember we can
[27:21] sit
[27:22] in fact maybe it depends on the version
[27:25] of kubernetes i've got
[27:27] and it's i'm probably revealing too much
[27:30] now
[27:31] that it isn't entirely useful to the
[27:33] people watching but the security context
[27:35] has changed a lot with the recent
[27:37] version of kubernetes which is 120
[27:39] which i actually think i'm running uh
[27:42] version yeah
[27:46] well client and 119 there okay so we
[27:48] might be okay
[27:50] we'll apply first and then i'll walk
[27:52] through the all those things that are
[27:53] going through my head
[27:55] uh so let's get pods and alex keep me
[27:59] honest here if there's anything i say
[28:00] that is gibberish just ask me to
[28:02] elaborate on it because sometimes i can
[28:03] be bad for that
[28:06] sweet okay well if anyone watching is
[28:11] like
[28:11] i have no idea what the hell this madman
[28:13] is talking about just
[28:14] comment and i will explain it i promise
[28:17] yeah i've got that doctrine
[28:18] open as well so if any comments um ask
[28:20] questions
[28:23] i just need this container name
[28:27] i'm going to change that next time i
[28:28] deploy this just to be fpm so it's easy
[28:31] for me to use the command line
[28:34] so we have storage yeah when logs are
[28:37] still owned by root
[28:39] so we still need to fix that
[28:43] now they'll be owned by ever the user of
[28:45] the processes
[28:47] so we could just change the security
[28:49] context of that
[28:51] and do
[28:54] run as
[28:58] id www data oh no i'm not inside that
[29:02] anymore
[29:04] 82 is that id always going to be the
[29:08] same
[29:08] or yeah it's built into your image so
[29:12] next time you do the build would it be
[29:14] 82 still
[29:16] no that'll be set by the fpm right that
[29:20] i would not expect that to change uh
[29:22] right you should be safe
[29:24] um i don't think you can do this the
[29:26] reason why is that this security context
[29:28] runs on
[29:29] the the node essentially is configured
[29:31] as
[29:32] part of the name species are set up so
[29:36] uh you will need to use the numeric id
[29:39] let's try and i'm going to rename this
[29:43] actually let's do that so we're going to
[29:46] just call
[29:46] that's the image where's the name there
[29:48] we go let's just call this fpm so it's
[29:50] easier for me to get enough
[29:52] and we'll call this one nginx
[29:55] okay now we can apply
[29:59] make sure it's running and we're gonna
[30:03] exec it entered this
[30:08] or ftm and ash
[30:12] and you can see when i type id i am now
[30:14] ww data
[30:16] if i run ps everything is www this is a
[30:19] much
[30:20] saner configuration and i'm hoping the
[30:23] empty dare
[30:26] all right okay so we need to fix that
[30:28] and if you don't have the empty
[30:29] developer would that not
[30:31] just make it work because
[30:35] will create that folder if they need it
[30:38] hey
[30:39] so you're okay but
[30:42] yeah yeah you're you're actually correct
[30:45] um maybe i'm over complicating this a
[30:47] little bit
[30:49] but also how come how come the files are
[30:52] still in by root
[30:53] is that because when we built the image
[30:54] it was running as groups
[30:58] yes um because
[31:01] do the do those files not need to be
[31:03] owned by wwe data as well so that
[31:06] fbm can process them no they're readable
[31:09] by anyone
[31:10] uh something else i would normally do as
[31:12] well is enable read-only file system
[31:14] so you know i actually don't want you to
[31:15] be able to write to anything which is
[31:16] why the empty dart's important because
[31:18] that will be somewhere we can write to
[31:21] yeah i just wish i could remember the
[31:23] file system thing that i want here
[31:26] so we're going to look it up
[31:29] so kubernetes security context
[31:34] and there is an fsu's fs group is that
[31:37] it
[31:42] where's that password
[31:47] yeah why is that not all completing for
[31:49] me so this might just be the version of
[31:50] kubernetes i've got
[31:51] it doesn't have this flag anymore um
[31:55] let's just put it in and see what
[31:59] oh happens really yelling at me isn't it
[32:05] unknown okay yeah that must have been
[32:07] removed then
[32:10] so let's see kubernetes
[32:13] empty their user permissions
[32:18] there is a way fs group
[32:22] damn it
[32:26] surely if they remove that they want to
[32:27] put like a deprecation flag to tell you
[32:28] what anyone's called
[32:34] no
[32:38] but it's definitely fs group which is
[32:40] good because i knew that's what it was i
[32:41] just
[32:42] don't know how to handle i mean we could
[32:43] use it in a container i'd like to try
[32:45] and avoid that of course uh
[32:49] in fact am i doing it in the wrong place
[32:51] that's what it is
[32:53] so this is the security context for the
[32:55] pod i bet you if i
[32:59] yeah there we go
[33:04] um that should create
[33:09] so do we want the user to be
[33:12] on um
[33:16] on the spec not on the pod or not
[33:19] uh it depends what user we have inside
[33:23] the engine x
[33:25] so let's let's take a look at that
[33:29] and take a look at our password file
[33:31] which is our source of users
[33:34] yeah engine externs is 101 and we don't
[33:37] have access to
[33:38] www data here at least i mean i
[33:41] don't see yeah no
[33:45] data is a fpm yeah
[33:49] let's try this um
[33:52] just out of curiosity more than anything
[33:54] there so
[33:57] because you'll use the 82 for the fs
[33:59] group
[34:00] but that would be applying it to the
[34:02] engine next one as well
[34:04] yep there's no empty dirt there so ah
[34:06] right so any applies if there's enough
[34:08] to do it
[34:12] well maybe well yeah there we go
[34:15] so if you haven't on the nginx one as
[34:18] well
[34:18] you wouldn't be able to specify the fs
[34:20] script for each individual container
[34:22] ipod there would you because they have
[34:24] different ids
[34:27] no for that i'd then be using an
[34:28] internet container that has a
[34:30] root user that changes the permission
[34:33] on the empty there which would be reused
[34:35] across the inner containers
[34:38] we can we can cover that if we think
[34:40] that it's important
[34:42] um but let's just try and let's try and
[34:44] get this working first and then we can
[34:45] maybe do some cleanup
[34:46] so you can see here we've got our uh
[34:49] grip right access to here and in fact
[34:51] that empty door just came with explicit
[34:53] permissions for anybody anyway so we
[34:55] actually didn't need to do that but i
[34:57] think it's
[34:58] that configuration parameter hopefully
[35:00] is useful for others if you're looking
[35:02] at a similar situation
[35:04] let's put forward
[35:08] so
[35:12] 8080 so we should be able to write the
[35:14] logs
[35:18] and now it's complaining that we've got
[35:19] some configuration missions so this is
[35:21] going to be that dot env file that you
[35:22] mentioned right
[35:24] uh yes it is okay so now we need a
[35:26] contact map
[35:29] so um let's create
[35:33] config map dot yaml
[35:37] spec this out this is our light of l
[35:40] config map
[35:42] um
[35:45] okay
[35:49] so there is a secret value in here i'm
[35:51] not that fussed about it being secret
[35:52] because i'm just going to delete the key
[35:53] and play account probably i'm never
[35:55] going to use that mail thingy again
[35:57] so i'm just not going to be too fussed
[36:00] about
[36:01] exposing them yeah you could you could
[36:03] just um after the
[36:05] after this um screenshot you can just
[36:07] click the refresh button and
[36:09] watch out it will be used right nice
[36:10] okay so
[36:13] we we really just want this env fail to
[36:15] be exposed
[36:16] as environment variables and a conflict
[36:19] map is our
[36:20] ideal way to do that now some of this
[36:22] isn't actually
[36:24] some of this i would bake into my image
[36:26] i'm not going to get
[36:27] dogmatic about that right now and we can
[36:29] talk about that uh
[36:31] once i've got it working but like you
[36:33] know the app name
[36:34] isn't something i'm going to want to
[36:36] change per environment
[36:38] conflict maps to me should only ever
[36:40] change variants
[36:42] for environmental things everything else
[36:44] should be baked into the image so the
[36:46] app name
[36:47] yeah i would probably put it in a docker
[36:49] image somewhere
[36:50] yeah there is something built into
[36:52] laravel already
[36:54] as well which is um
[36:57] you can sort of cache the uh what they
[37:01] call config
[37:02] so um which is their.emv files and other
[37:06] things that
[37:06] are used for the application they can
[37:08] all get cached and there's a command to
[37:09] do that so
[37:10] it doesn't actually read anything from
[37:11] the environment however that would
[37:13] require it to be
[37:14] then stored within the actual image
[37:17] itself but
[37:17] not so i guess that's
[37:21] a decision that you can make i'm sure
[37:23] there's some
[37:24] yeah we'll talk about that uh in a
[37:26] moment i'm sure i could like
[37:28] regex i'm i'm kind of looking at it
[37:29] going i'll just be quicker to type it
[37:32] because i bet me going i could just
[37:33] reject all this
[37:41] so what we want to do is
[37:44] all you want to do is just change the
[37:45] equals to a column answer yeah
[37:52] why is that not letting me register oh
[37:53] does my vs code them not support that
[37:59] time for trusty command on um
[38:02] you know you know what's going to happen
[38:05] or just come on death
[38:07] yeah let's just do it this way so
[38:10] change equals paracolon space
[38:16] go
[38:20] and then and then okay so now we need to
[38:24] yeah that needs to be a string billion's
[38:27] not supported
[38:29] now we want our host so this is going to
[38:30] be the service name that we've provided
[38:34] which i believe is mariadb we can run
[38:37] get
[38:37] services
[38:42] yep so we have our database available at
[38:44] that name
[38:45] on that port that's our database our
[38:47] username is laravel and our password as
[38:49] laravel
[38:50] and this would be a secret let's get it
[38:53] working without and then clean it up
[38:54] don't let me forget that yeah
[38:58] broadcast driver i don't know what that
[38:59] means i don't know what that means i
[39:00] don't think we don't use it
[39:01] so you can ignore all of those ones we
[39:03] didn't care about that the session
[39:04] driver actually
[39:05] um that wouldn't we're not using
[39:07] sessions in this bitcoin you can know
[39:08] that
[39:09] um in production i would normally change
[39:10] that to uh redis or database
[39:16] do we need the aws access stuff no
[39:20] that's just because you can buy with the
[39:23] file system
[39:24] plugins you can upload straight to s3 by
[39:27] um
[39:28] by default so that's all guys
[39:35] how come it's complaining about numbers
[39:37] like 25 25
[39:40] i thought yeah we'll support introducing
[39:42] that
[39:44] it does uh
[39:48] what's it saying
[39:52] i think the config map just expects a
[39:54] string to be honest
[39:56] yeah like everything strings
[39:59] we're not running memcached we're not
[40:01] running red
[40:02] no all right i think
[40:08] that will be enough so let's apply that
[40:11] now
[40:12] and then update our deployment to use it
[40:15] so this is really easy um
[40:19] what needs to is it nginx or is it fpm
[40:22] both
[40:23] um fpm would be what requires it because
[40:25] it's the php for every
[40:26] process that's running yes okay so env
[40:30] from fun effect map ref
[40:36] uh
[40:38] the name of the conflict map oh what did
[40:41] they call it laravel
[40:43] yep yep
[40:46] uh does that just like basically
[40:50] export inside of the image before it
[40:52] deploys it
[40:54] yes it will take all of these keys and
[40:57] make them environment variables which is
[40:58] how larval works i don't even need to
[41:00] change anything
[41:03] so let's reapply our deployment
[41:08] so that would behave basically the exact
[41:10] same way as
[41:11] if you'd baked it into the image before
[41:13] you deployed it at all
[41:14] i guess it would just be a linux
[41:18] environment
[41:22] all right let's see how far we are now
[41:27] the application key might not like that
[41:28] i'm not sure okay
[41:33] all right let's check our logs
[41:36] yeah now that's one of the things i was
[41:39] going to complain about next right is we
[41:41] actually don't want to log to a fail in
[41:42] any container environment
[41:44] that is generally a full power and you
[41:46] want to log the standard
[41:48] out so first let's look at the logs
[41:51] and then change that
[41:55] so our problem is
[42:01] it's trying to write to something then
[42:02] we have a read-only fail system
[42:04] what's it trying to write to
[42:08] um oh it caches your views
[42:11] so framework views is like um
[42:14] it's a cash thing because it comes with
[42:17] something called blade
[42:18] which is a template language like twig
[42:21] that sort of style of um
[42:23] that sort of style thing so it tries to
[42:24] write those two
[42:26] problems yes and if everything is always
[42:31] but that's just this framework folder
[42:32] right yeah
[42:36] yeah assume that all of those have been
[42:38] trying to do it into sessions cache
[42:40] they're not testing these as you when
[42:41] you want tests and also views
[42:44] okay so that's all empty so what i'm
[42:46] going to do is empty there that too
[42:52] i want to try and keep this as a
[42:53] read-only file system for as long as
[42:55] possible before i admit defeat
[42:58] so we'll bring in this cache and we're
[43:01] going to mount that
[43:04] so would you normally have like a
[43:07] attempter sort of thing that could be
[43:09] written to for
[43:11] say if somebody was to upload a file
[43:13] that needed processing before getting
[43:14] moved on to like s3 would you have like
[43:16] attempter
[43:17] configured which is wrapped up and only
[43:18] that
[43:20] yes so i would definitely use the
[43:22] volumes key up here to provide something
[43:24] that was ephemeral now i would use an
[43:26] empty dirt definitely for
[43:28] like a local kubernetes environment and
[43:30] some production environments
[43:31] i may like if i need to guarantee that
[43:34] file exists after a pod restart i'd
[43:36] probably use like a
[43:37] persistent volume or a host path
[43:39] depending on how my cluster is
[43:40] configured but
[43:41] i would use a volume of some kind for
[43:43] anything that needs right access
[43:45] the reason being is like you know most
[43:48] attacks especially against
[43:49] uh php based content management systems
[43:52] is generally through
[43:53] some really contrived and illegal upload
[43:56] that executes an arbitrary script and
[43:57] then rewrites over your code
[44:00] and you could just you know just one
[44:01] read-only file system argument
[44:04] just stops all that as long as you don't
[44:06] mind going through the process
[44:08] uh of making sure you could write to
[44:10] your logs in your cache
[44:11] which i'm going to try and do now so
[44:14] let's try uh redeploy
[44:18] let's get our pods oh and let's change
[44:20] the login to standard out like we don't
[44:21] want to log to file anyway we want to be
[44:23] able to use the logs command
[44:25] so how do i configure that with laravel
[44:28] um
[44:28] change the env to sdd err
[44:32] [Music]
[44:34] so what am i changing change stuck there
[44:36] to std
[44:37] er
[44:40] is that correct okay
[44:44] yeah yeah that'll do it
[44:49] um there's also actually a standard out
[44:51] right
[44:52] yeah that just send it straight to
[44:53] something okay let's do that
[44:56] uh let's reapply
[44:59] and make sure i'm in the position that i
[45:01] kind of want to be in so uh
[45:04] yeah that's the conflict map i need to
[45:05] deploy
[45:08] and then i'll need to delete the pod to
[45:10] get that new configuration
[45:17] so now i should be able to run logs
[45:20] against this
[45:23] and i have the fpm logs you know if you
[45:26] hit the
[45:29] uh browser you should see something
[45:30] locked i think because i don't think
[45:32] we've fixed the error that we have
[45:33] before did we
[45:35] uh i hope so uh let me run the port
[45:38] forward from another location
[45:40] we can keep our logs up oh it's going to
[45:44] split my terminal but i think that's
[45:45] just going to make it more confusing
[45:48] all right so there is our logs
[45:57] well something's logging perhaps
[46:08] configuration is obviously not quite as
[46:11] simple as that
[46:13] i'm assuming that we're still going to
[46:15] have something in that
[46:17] storage logs
[46:26] yep
[46:30] this is cat so
[46:33] what field
[46:36] on car and valley
[46:40] um i'm i don't go to create logger
[46:44] standard out is not defined just oh so
[46:47] i trusted you so you're an option
[46:51] okay now
[46:56] if you open up the code in conflicts
[46:58] like i would expect it to be
[46:59] dev standard though like that um
[47:06] let's google that's what it's here for
[47:08] right so log
[47:09] to standard
[47:25] and there's another option which we can
[47:26] just use error log which will put it in
[47:28] the
[47:29] fpm log by default and that should put
[47:31] it into the standard
[47:32] log first
[47:36] all right what we have already should
[47:50] work
[47:52] no that won't work because um
[47:56] it's being passed through to monologue
[47:57] the um php
[48:00] body library
[48:04] let's see
[48:12] okay fpm
[48:25] yeah we're gonna have to add the service
[48:26] so i don't have to keep doing that but
[48:28] let's do it more time for now
[48:41] all right let's go back in
[48:49] uh fpm
[48:51] [Music]
[48:53] storage logs cat lock
[48:58] did that field to set up please provide
[49:00] a valid cache path
[49:06] uh unable to create configured bloggers
[49:08] is this because of the empty dev but you
[49:10] create a framework i think it expects
[49:12] for the cache form to exist you might
[49:13] need to create multiple empty first
[49:16] i don't think it might not create that
[49:17] folder okay
[49:19] i'm also worried about this logo yeah no
[49:22] that's definitely an issue
[49:23] um so unable to create complete logo
[49:26] would to me
[49:31] i'll leave that as an exercise for
[49:32] another day set up logging um rather
[49:34] than
[49:35] if you drink it up to syslog you just
[49:38] try that one last
[49:38] uh one last thing because i should put
[49:40] it straight through as well would it not
[49:42] no syslog may look for syslog in the
[49:44] container which won't exist
[49:47] oh okay all right let's ignore it
[49:50] um
[49:55] and let's do
[50:00] cash and we're going to need sessions
[50:07] and again i don't really want to spend
[50:09] too much time fighting on things that
[50:10] aren't that important so i can always
[50:12] just disable that if this doesn't work
[50:13] is there anything else required in the
[50:15] framework directory
[50:17] um views views
[50:23] i think there's one called testing as
[50:24] well with measurement i don't know what
[50:25] testing
[50:26] is
[50:31] do i have them here uh storage
[50:35] framework cache sessions testing tools
[50:38] right okay
[50:42] i mean i haven't just expected to create
[50:44] them if they're not there
[50:45] i find that i i do as well but that's
[50:48] all i can
[50:49] and okay modifier deployment
[50:55] oh yeah i've got to actually add them
[51:06] so we need testing
[51:10] sessions fears
[51:16] all right take 16.
[51:22] well we're not going to get any logs
[51:23] okay so
[51:25] let's just fix the port forward
[51:38] right that's progress we're not getting
[51:40] a white screen anymore
[51:42] so let's see what we are
[51:46] fpm ash storage logs
[51:49] cat log so now it's complaining
[51:53] oh yeah so it doesn't like my i just put
[51:55] a random string there what's that
[51:57] supposed to be
[51:58] um there's some sound commands hpr sound
[52:00] key colon generate
[52:02] um if you just run that inside of the
[52:04] fpm container
[52:06] that should um
[52:11] key colon generate
[52:22] it's trying to write it to env um i'll
[52:25] create one locally and just send it here
[52:28] can i not just print it out yeah
[52:31] sure there we go okay okay cool nice
[52:35] i hate it when tools are fighting
[52:36] against me rather than
[52:38] doing my bedding right okay
[52:42] um um and i've never seen it with
[52:45] basically
[52:48] well maybe that's just a helper
[52:54] all right uh let's just apply the whole
[52:56] directory for a bit of quickness
[52:58] make sure our pods rotate
[53:02] oh i only changed the config map so i
[53:03] need to delete my pods myself
[53:10] and now we can report forward again
[53:18] and finally i'm really hoping we see a
[53:20] database migration letter here
[53:24] oh our application the reason why you're
[53:27] getting that works because we're not
[53:28] requiring any databases
[53:30] at the moment but that is proving that
[53:32] the asset compilation works as well
[53:33] because
[53:34] that's using um terawin to get the data
[53:37] there
[53:38] all right it's production now i'll see
[53:40] you there thanks
[53:45] um so that's actually covered one of the
[53:46] things on the list anyway though that's
[53:48] the
[53:48] secrets and environment stuff there is
[53:51] some
[53:51] thing on my list which has happened a
[53:53] few times whilst you've been doing that
[53:54] which
[53:56] i assume it's not the right way of doing
[53:57] it you've just been deleting pods
[53:59] to get it to basically redeploy
[54:04] um probably a better way doing it than
[54:07] that i assume
[54:09] unfortunately not so that the problem is
[54:11] is that
[54:13] when you modify a conflict map it gets
[54:14] updated in real time
[54:16] pretty much within your deployment um
[54:20] so like the files will just be synced if
[54:22] there's a fail mount i think the
[54:23] environment variables
[54:25] i think they still update in real time i
[54:27] can confirm but i'm not 100 confident
[54:29] your application is really expected to
[54:30] notice those changes and reload
[54:32] uh but most applications don't and one
[54:35] of the ways to get around it
[54:36] is to include the sha of the conflict
[54:39] map
[54:40] as an annotation on your deployment
[54:41] which forces a reload every time
[54:43] you modify the config map it's a bit
[54:45] hacky
[54:46] and there are some controllers that can
[54:48] also run inside the cluster that monitor
[54:49] for changes in the contact map and
[54:51] rotate your pods for you
[54:53] so there's a few ways to do it but
[54:55] honestly for like this kind of
[54:57] environment
[54:57] the lean is the right way to do it
[55:00] however something you said that we
[55:01] tackled that we haven't was secrets
[55:03] um i wouldn't put a secret in this file
[55:07] so let's fix that let's take out this
[55:09] app key
[55:11] and let's create a secret channel
[55:14] i know and this is really gonna it's
[55:17] gonna feel weird
[55:18] because
[55:21] i'm solving one problem in a very
[55:24] similar way to the conflict map anyway
[55:26] and i'll try and do my best to explain
[55:27] why this is
[55:28] uh more why this is better
[55:32] so
[55:37] so this is a secret
[55:41] i am storing this as ammo and my
[55:43] repository right now so it is no more
[55:45] secret than a config map
[55:47] granted however you're very you're
[55:50] unlikely to apply your
[55:52] secrets to your cluster in this way um
[55:54] you may be using vol
[55:55] or some other kms system to provide
[55:58] these as
[55:59] and to get these into your cluster but
[56:01] you want them to be a secret inside of
[56:03] your cluster because they have different
[56:04] r back
[56:05] rules compared to a config map right as
[56:07] generally config maps have
[56:09] loose airbag most people can have access
[56:12] to them
[56:12] they're also consumable from within the
[56:14] pods you want to be able to lock
[56:16] that down and you want to be able to
[56:17] lock the pods down as well so that
[56:18] nobody can execute into it and just grab
[56:20] the secret
[56:21] um so well from a very
[56:24] naive perspective and look at it and i
[56:26] use the wrong word from a very
[56:28] well from this example it doesn't seem
[56:30] like we're improving the security at all
[56:31] just by using the secrets
[56:33] you are as long as you get them into the
[56:34] environment correctly
[56:36] the other thing i want to kind of cover
[56:37] is that uh well first
[56:39] little fail um there's two keys on a
[56:42] secret
[56:45] string data and data and and
[56:49] actually expects your data to be base64
[56:52] encoded
[56:53] so if i do base64 paste this
[56:56] in and grab this
[57:02] in fact that's not going to work because
[57:03] of the new line
[57:05] so let me just copy that properly
[57:09] and we should actually have done like
[57:11] echo dash
[57:13] and which means no new line right
[57:16] yeah and then base 64 and this will get
[57:19] its agile value
[57:25] so both of these are correct so when i
[57:28] apply
[57:28] and in fact let's just change this so
[57:31] we'll call this string key instead of
[57:33] that key
[57:33] i can't remember if the kubernetes
[57:35] control plane will allow me to have data
[57:37] and string data but we're going to push
[57:38] our look and see what happens
[57:40] so yeah it doesn't care
[57:43] cool now we should actually see that
[57:45] both these values are the same
[57:48] um so we'll grab our ladder bell dash oh
[57:52] yamaha
[57:54] i think it's built secret
[57:59] and if we look at the data fields yeah
[58:02] you see we actually get the same value
[58:03] here
[58:04] so string data is a helper that when you
[58:06] apply something to the cluster
[58:08] it knows that you haven't base64 encoded
[58:10] it yet and it will base64 encode it for
[58:12] you
[58:13] regardless you get the same value at the
[58:15] other end so string data
[58:16] a helper good in some environments uh
[58:20] data base64 encoded not a secret
[58:23] but again you wouldn't apply secrets
[58:25] typically in this fashion
[58:27] for production use cases you would use
[58:29] like sops fry mozilla
[58:32] uh sealed secrets are my personal
[58:35] favorite the capitan
[58:37] project um so these all handle it
[58:39] slightly differently
[58:40] um sops and sealed secrets will use well
[58:43] in fact they all they'll do the same way
[58:44] they'll encrypt stuff but the way that
[58:46] you interact with the tool is slightly
[58:47] different
[58:48] um i don't know if there's gonna be like
[58:51] a quick thingy here
[58:57] no because we don't have a kubernetes
[58:59] specific thing it doesn't matter
[59:01] so sops allows you to encrypt it and
[59:02] store the encrypted file within get
[59:04] which means you can apply it you just
[59:06] have to remember your continuous
[59:07] integration pipeline to
[59:09] to decrypt it before you do the the
[59:10] apply and there are some things that can
[59:13] run in a cluster to try and make that
[59:14] easier and more secure
[59:16] but it's a really good way of doing it
[59:17] sealed secrets does the same
[59:19] it stores a private key inside of your
[59:21] kubernetes cluster
[59:22] you can use the sealed secrets command
[59:24] line to reach out encrypt a value
[59:26] and you get a text-based secret like
[59:29] this
[59:29] with obviously an encrypted string which
[59:32] is still secret
[59:33] and then finally there's the capitan
[59:35] project which
[59:36] does secret management it hooks up to
[59:38] all the kmscs and vault
[59:39] so if you're already deploying to a
[59:41] cloud provider with a kms this is
[59:43] honestly this is just the best way to do
[59:45] it and you can define them in your ammo
[59:47] and they'll be
[59:48] they'll be encrypted for you and only
[59:49] decryptable and a cluster that has
[59:51] access to that kms so you can use cloud
[59:53] provider i am rules
[59:55] i'm not going to say any more about it
[59:56] because secrets would be deviating us
[59:58] down a path
[59:59] of a lot of time and i don't want to
[1:00:00] take up too much of your time
[1:00:02] and in fact we only have like 25 minutes
[1:00:04] left so
[1:00:06] let's see did that all make sense that
[1:00:09] wasn't too much waffle
[1:00:12] something kind of um with ansible where
[1:00:14] you use that scoreboard
[1:00:16] but that would have you'd have the
[1:00:18] encrypted locally sorting gate and then
[1:00:19] when you're trying to apply it
[1:00:20] and try and deploy that you use you
[1:00:22] provide your volt key which
[1:00:24] is just the battery if you type in it
[1:00:26] deployment time and decrypt it and send
[1:00:28] the values over
[1:00:30] something to kind of similar to what
[1:00:31] sounds like um
[1:00:37] and no surprises we pass our secret
[1:00:40] through
[1:00:41] in exactly the same way there are finer
[1:00:43] grade controls you can mount in specific
[1:00:45] keys
[1:00:46] and make them optional change the names
[1:00:48] within the container
[1:00:49] there's a bunch of stuff you can do okay
[1:00:52] um
[1:00:53] let's make sure we haven't broken
[1:00:54] anything
[1:00:57] let's apply that whole directory
[1:01:03] here's our new pod
[1:01:06] port forward
[1:01:09] and we should still see right okay
[1:01:14] uh i can't believe we started off saying
[1:01:16] let's run database migrations we're like
[1:01:20] a fair chunk of our way through this we
[1:01:22] haven't done it yet so let's actually
[1:01:24] run these migrations now
[1:01:25] so kubernetes expects us to leverage
[1:01:28] something called an init container
[1:01:30] and now if we go to our container
[1:01:32] definition
[1:01:35] here and we can just say edit containers
[1:01:39] and we can provide it a name we'll call
[1:01:41] this database
[1:01:42] migrations and it takes pretty much that
[1:01:45] same spec
[1:01:46] that you're using um for in fact it is
[1:01:49] the same spec for your containers
[1:01:51] you're just trying to overwrite the
[1:01:53] behavior in a way that makes sense for
[1:01:55] you to run certain commands so
[1:01:56] you know here i'm going to say run fpm
[1:01:59] and the thing i want to change
[1:02:01] is that i need access to
[1:02:04] well i want to run a different command i
[1:02:07] want to run
[1:02:08] php and then i'm going to provide some
[1:02:10] arcs
[1:02:12] the arcs are going to be artisan
[1:02:16] db is that right yeah just just migrate
[1:02:21] just migrate so just php our design
[1:02:23] migrate
[1:02:25] yeah and then you'll also need to do um
[1:02:27] double dash
[1:02:28] false i think because it will by default
[1:02:30] for a warning sign you're running this
[1:02:32] in a production environment all right
[1:02:38] let's just do it i'm feeling it an entry
[1:02:41] point because it
[1:02:42] that needs to enter at the bottom
[1:02:44] kubernetes doesn't call it an entry
[1:02:45] point so in kubernetes use same language
[1:02:47] so it's command and args
[1:02:49] whereas docker yes they would call it
[1:02:52] what i mean is um for the file path of
[1:02:56] where you're running php
[1:02:57] from uh do you know because
[1:03:01] every time i've exec into that container
[1:03:03] you've put me into the working door
[1:03:04] which seems to be the correct location
[1:03:07] okay if i might just set up properly
[1:03:08] that is pure coincidence
[1:03:10] yeah and your docker file let me just
[1:03:13] because you haven't done it for nginx
[1:03:14] but you have done it for um for fpm
[1:03:17] so yeah that's yeah yeah okay yeah you
[1:03:20] would want that in your
[1:03:21] next one as well uh now i forgot to set
[1:03:23] the image pull policy to never which is
[1:03:25] why that's failing
[1:03:26] so let's top that up
[1:03:30] so you'd only have it never in because
[1:03:33] you're doing this locally if i was doing
[1:03:34] this on a production you get rid of all
[1:03:36] of the nethers and
[1:03:37] the actual path of the image would be
[1:03:42] private.com yeah you always include the
[1:03:45] container registry
[1:03:46] i like to run my own registry within my
[1:03:48] clusters the caches the images i
[1:03:50] generally use a pool policy
[1:03:52] if you know if it's not available if
[1:03:54] it's not present on
[1:03:56] on the machine i don't do an always pull
[1:03:58] generally because i do
[1:04:00] i don't use ephemeral tags like
[1:04:02] lyricists and such that you know i would
[1:04:03] use a proper
[1:04:04] um content
[1:04:08] all right let's see why this is failing
[1:04:10] i'm assuming that the migrate command is
[1:04:12] trying to rate to a fail
[1:04:14] probably and that my we're going to have
[1:04:17] to sacrifice my read-only fail system
[1:04:19] but
[1:04:19] let's i don't believe it does write any
[1:04:21] files
[1:04:22] all right so we want the logs for the
[1:04:24] database migrations
[1:04:26] we're getting connection refused okay
[1:04:29] so did you
[1:04:32] create i didn't give it the environment
[1:04:34] variables
[1:04:38] so we need this to be copied
[1:04:41] to here
[1:04:44] let's reapply
[1:04:48] and see what we got
[1:04:53] it worked
[1:04:56] you don't seem convinced uh
[1:04:59] i typically check the database to make
[1:05:01] sure my breaking work
[1:05:03] all right so let's scrap this let's just
[1:05:06] see
[1:05:07] database migrations
[1:05:11] um yep there we go no okay
[1:05:15] is there an endpoint in your laravel
[1:05:17] application that will allow us to
[1:05:19] consume that database at all yep so
[1:05:22] i've created a few endpoints one of them
[1:05:24] is called create dash
[1:05:26] posts and that will create just five um
[1:05:29] by posting the various
[1:05:34] create slash post or dashboard
[1:05:37] all right like so uh yep
[1:05:40] i know that's a little difficult to read
[1:05:42] but so that should have done it
[1:05:44] i didn't give any up or don't we thought
[1:05:46] i'd be in white that's right kind of
[1:05:47] get posts that is a geckos oh no no
[1:05:51] sorry um now if you go to slash posts
[1:05:56] there you go but yeah yeah
[1:05:59] great awesome so migrations is working
[1:06:02] yeah really simple i mean any containers
[1:06:05] they are the best way to handle this
[1:06:06] thing of course there are caveats i'm
[1:06:08] not going to say go and add this to all
[1:06:09] applications immediately
[1:06:11] they need to be an important you have to
[1:06:14] be able to run them these will
[1:06:15] like in fact let's show that when i
[1:06:17] scale this up to five
[1:06:19] those migrations are going to run on
[1:06:20] every deployment every time i kill a pod
[1:06:22] so you really need to make sure
[1:06:24] that they don't collide
[1:06:27] there's locking you know you're going to
[1:06:29] potentially have two running very close
[1:06:30] to each other and they have to be out
[1:06:32] important
[1:06:34] so i'm assuming with the orm that
[1:06:37] laravel is using that you get all that
[1:06:38] for free
[1:06:39] most orms do provide something like that
[1:06:41] so you should be good
[1:06:43] i'm not sure about issues so because
[1:06:45] they are quite
[1:06:46] good on like um
[1:06:49] the whole like high availability side of
[1:06:51] things so i'd assume that that's
[1:06:53] important
[1:06:53] i would assume your migrate commander
[1:06:55] does a lot on the entire database
[1:06:57] and in fact we could probably trigger
[1:06:59] that by you know
[1:07:01] deleting the database spinning it back
[1:07:02] up empty running a migrate and trying to
[1:07:04] hit
[1:07:04] create posts at the same time or get
[1:07:06] posted at the same time we'd probably
[1:07:07] see it wait for a while before it got
[1:07:09] access to the table again oh the
[1:07:10] database
[1:07:11] okay what's next on your list what we've
[1:07:13] got uh 20 minutes
[1:07:15] so q jobs is probably the big one huge
[1:07:18] schedule address
[1:07:20] all right so kubernetes exposes a
[1:07:22] primitive
[1:07:24] called jobs and which are just like
[1:07:26] crunch ups
[1:07:30] uh i don't think i'm going to be able to
[1:07:32] oh i do
[1:07:33] i love this plugin so
[1:07:36] we have you know just like all other
[1:07:38] kubernetes manifest really simple
[1:07:39] specification
[1:07:41] and we can specify this is the time to
[1:07:43] second
[1:07:44] time to live seconds after finished who
[1:07:46] knows where that is to have help
[1:07:49] uh late time job is finished execution
[1:07:52] yeah whatever okay
[1:07:53] we specify the container and we specify
[1:07:55] the command now
[1:07:57] you'll also want to be able to tweak
[1:07:58] awareness runs
[1:08:00] and i'm using the wrong object
[1:08:07] crown job
[1:08:11] i'm going to show my own ignorance i've
[1:08:13] never been able to remember how this
[1:08:14] works now
[1:08:20] kubernetes i spent a lot of my time in
[1:08:22] documentation
[1:08:25] there we go there is a thing called cron
[1:08:26] jobs yeah i just couldn't remember what
[1:08:28] this
[1:08:29] was because i've seen like online but
[1:08:33] all right some things just refer to v1
[1:08:37] and some things referred to like
[1:08:38] something documented.b1 yeah
[1:08:41] um i'm not sure why that yelled at me
[1:08:44] then maybe it's because the spec was
[1:08:45] wrong
[1:08:47] or maybe never maybe that's not been
[1:08:49] promoted yet actually
[1:08:51] so yeah okay
[1:08:54] um it's not crown jobs haven't had a v1
[1:08:56] yet but jobs have so
[1:08:58] there we go let's just copy the whole
[1:09:01] thing and modify it or
[1:09:02] to do our bidding so we'll call this
[1:09:04] ladderville i'm just going to keep
[1:09:06] calling everything maribel
[1:09:07] we can use regular cron cell syntax to
[1:09:09] specify the job
[1:09:11] um i don't know how to generate that
[1:09:13] most of the time
[1:09:17] yeah crowdmaker i think this is the one
[1:09:19] i use
[1:09:21] let's just say run every five minutes
[1:09:31] uh why wouldn't you just do um style
[1:09:35] i have because you wanted to run every
[1:09:36] minute
[1:09:38] at the crown helper in the laravel
[1:09:42] um then inside and inside of the
[1:09:46] console kernel determines what jobs
[1:09:48] inside of there should run
[1:09:50] and what frequency so you would run this
[1:09:52] every minute
[1:09:54] okay so i guess i don't understand i've
[1:09:56] never built a laravel application so
[1:09:58] let's try and cover a few basic
[1:09:59] questions then
[1:10:00] um now is the queue processor
[1:10:04] a long-running process that should be
[1:10:06] deployed as an employment or
[1:10:07] is it actually a cron job that runs
[1:10:09] regularly uh sorry so it depends
[1:10:11] are we dealing with a huge job here
[1:10:12] where we're dealing with the scheduled
[1:10:14] tasks because there's two things that
[1:10:16] need covering anyway
[1:10:18] uh okay so i'm assuming the schedule
[1:10:19] tasks the chrome job right
[1:10:21] yes okay so you can give it to the star
[1:10:23] star star star star
[1:10:24] just straight up every minute and then
[1:10:28] all you do is you have like the migrate
[1:10:30] command you have one entry point which
[1:10:31] is just
[1:10:32] a schedule call on run
[1:10:40] yeah schedule call on run um once you've
[1:10:44] done that
[1:10:45] every minute it just deals with itself
[1:10:46] based on your hp
[1:10:52] okay so we call this scheduled
[1:10:56] uses the same fbm image what command are
[1:10:58] we running
[1:10:59] um schedule call on run
[1:11:03] is that all uh let me just check if
[1:11:06] there's some forces
[1:11:13] all right let's apply it so
[1:11:17] air jobs and then like all the other
[1:11:20] kubernetes resources we type get jobs oh
[1:11:26] not a crown job
[1:11:27] i called it a job yeah here we go
[1:11:30] and we can wait uh let's within a minute
[1:11:34] we should see a pod get scheduled
[1:11:35] which will spin up run that command shut
[1:11:37] that down and then that'll look every
[1:11:39] minute doing the same thing
[1:11:41] and by pure coincidence we're about to
[1:11:43] hit quarter past
[1:11:45] and i've got a job in there but every
[1:11:46] five minutes sends an email
[1:11:48] so we should see you know just
[1:11:51] pure for instance on that but
[1:12:00] [Music]
[1:12:08] so oh it crashed
[1:12:11] i don't know is it trying to rate her
[1:12:14] fail
[1:12:16] um it will be won't it i don't think it
[1:12:19] should write
[1:12:21] uh all right let's see unless it ends up
[1:12:23] maybe it writes like a cache file thing
[1:12:25] oh no could not open input failed
[1:12:27] schedule run what have i got wrong
[1:12:29] oh you can give it a second
[1:12:47] we actually had a few comments there as
[1:12:49] well which we were too busy focused on
[1:12:51] that so
[1:12:52] uh frank and nate both commented that we
[1:12:55] missed the artisan
[1:12:56] thank you uh
[1:13:01] so that's that archive it i don't know
[1:13:03] if i applied that because
[1:13:05] i i got really confused when you
[1:13:07] disappeared and then realized the
[1:13:08] software crashed so
[1:13:09] yes these things reconnect and stuff
[1:13:14] so it says unchanged
[1:13:18] there we go so we this is now completing
[1:13:20] every minute
[1:13:21] we've had two of them since the crash
[1:13:24] obviously this one failed
[1:13:25] um so do we not want that to kill itself
[1:13:28] off immediately
[1:13:29] as soon as it's got the exit and there's
[1:13:32] no need for a time to life on that is
[1:13:34] that because
[1:13:34] it's never going to reuse the same
[1:13:35] command again
[1:13:38] we'll leave it for now i don't think
[1:13:39] it's terribly important
[1:13:42] um will they clean themselves up once
[1:13:44] the ttl gets hit i guess
[1:13:48] yeah did that just crash again oh that's
[1:13:51] that's just a broken one so i can just
[1:13:52] delete that
[1:13:56] because would that not mean that every
[1:13:58] minute a new pod is created and that
[1:14:00] isn't being cleared out
[1:14:02] so eventually we're just running out of
[1:14:03] memories
[1:14:05] no these ones are gone they're completed
[1:14:07] so they don't take up any resources
[1:14:08] anymore
[1:14:09] so okay so that seems okay
[1:14:14] uh i guess if we wait another two
[1:14:15] minutes we should see
[1:14:17] the email come in here yeah
[1:14:20] at 20 past um but you said there was one
[1:14:22] other type of job so let's try and
[1:14:24] handle that one then
[1:14:26] yeah so this is the more um
[1:14:30] i guess complicated one um what you can
[1:14:33] have
[1:14:33] in laravel is um huge jobs so you can
[1:14:37] queue it up using both different queue
[1:14:39] drivers
[1:14:40] with ses and you can play database redis
[1:14:42] rather mq all those sort of things
[1:14:44] um but the way of using that is the same
[1:14:47] so it doesn't make any difference to us
[1:14:50] um what we want to do there is have a
[1:14:54] command that's running
[1:14:55] longer it's a long running process in
[1:14:56] the background that
[1:14:58] um runs the rsan q colon work
[1:15:02] and that's all that we require
[1:15:06] um but then it gets a bit more
[1:15:07] complicated than that you can have
[1:15:08] different named queues and have
[1:15:10] different number of workers per cues and
[1:15:12] things like that i guess
[1:15:14] yeah that's just going to be a new
[1:15:15] deployment for me i mean long-running
[1:15:17] process means it's a deployment i want
[1:15:19] to be able to scale up and down
[1:15:20] depending on how many workers i want
[1:15:22] as well as tweaking the parameters so
[1:15:25] you know we could
[1:15:26] i mean we probably would just copy this
[1:15:29] uh and call it q
[1:15:32] worker
[1:15:36] and we're not going to need the nginx so
[1:15:37] we can remove that
[1:15:45] do we do you think we'll need logs cache
[1:15:47] test i'm going to affect you know i'm
[1:15:48] just going to keep it i don't want to
[1:15:49] i think we'd need it all because the
[1:15:51] framework would still hate those well
[1:15:53] maybe not like views and stuff but
[1:15:58] all right so we update our labels to be
[1:16:00] q worker
[1:16:03] worker and then we just modify the
[1:16:05] command
[1:16:06] we don't need our init container at all
[1:16:12] and here we're just going to say
[1:16:15] oh we don't specify the command we're
[1:16:16] using the unbuilt one
[1:16:18] so here we just say php again
[1:16:22] we specify the args and we're going to
[1:16:24] run sorry what was the command artisan
[1:16:27] artisan and then q column work
[1:16:32] cola yeah
[1:16:35] and then you need to pass so that will
[1:16:37] work by default
[1:16:38] that will run the what's called uh all
[1:16:41] the three queues in marbella named and
[1:16:42] the default is just called default
[1:16:44] but what you can do is you can then pass
[1:16:46] through double dash queue equals
[1:16:49] and give it a conceptual string of
[1:16:50] different queues so you can
[1:16:52] just default that and that from the
[1:16:53] default one um so if you have different
[1:16:56] higher my priority queues you can make
[1:16:57] the high priority queue have ten workers
[1:16:59] low priority you have
[1:17:00] two workers yeah and that's
[1:17:03] that exact reason is why i would use its
[1:17:05] own deployment
[1:17:07] for each of the different queue
[1:17:08] semantics i've got so that i can really
[1:17:09] define the quality of service and how
[1:17:11] quickly i need to process
[1:17:12] and how many workers and how many
[1:17:13] replicas not all cues i would imagine
[1:17:16] at least in applications i've written in
[1:17:17] the past would be considered equal
[1:17:19] and i'd want to be able to tweak that it
[1:17:21] may seem like oh i'll just add a new pod
[1:17:23] a new container to my main pod but
[1:17:26] i don't think that would be necessarily
[1:17:27] the right way to handle that
[1:17:30] let's apply
[1:17:35] where are we
[1:17:38] cute workers right we now have five
[1:17:40] queue markers can we
[1:17:42] do we can we confirm that yes we can so
[1:17:45] in the groups if you go to slash q
[1:17:48] jobs it will should send three emails
[1:17:52] oh first of all if we check the email
[1:17:54] provider we should have an email from
[1:17:55] the cron dropping there now
[1:18:00] [Music]
[1:18:10] jobs it should send
[1:18:13] three more emails up here we go
[1:18:17] we have our keyworkers easy peasy
[1:18:20] um so there's something that you can
[1:18:22] because php isn't really designed for
[1:18:24] long running at least it was never
[1:18:26] initially designed for long-running jobs
[1:18:28] um it's kind of basically a sort of
[1:18:32] hacky way of doing it
[1:18:34] the key workers there at the moment and
[1:18:36] so you can sometimes get remember the
[1:18:37] issues with that
[1:18:39] so reliable does provide something
[1:18:40] called max jobs which is another flag in
[1:18:42] your past which means that you'll kill
[1:18:43] off that
[1:18:44] that worker sends like an exit signal to
[1:18:47] it after
[1:18:48] x number of jobs if you were to do that
[1:18:51] with
[1:18:51] the container would that spin up a new
[1:18:55] one which is what you'd expect
[1:18:57] or would that then start like a whole
[1:18:59] cascade of issues
[1:19:02] yeah what i would use is the resource
[1:19:04] limits here you know i've already
[1:19:06] defined how much how many resources i'm
[1:19:08] happy for these queue workers to consume
[1:19:10] so like kubernetes is going to restart
[1:19:12] it when it
[1:19:12] when it starts to break these limits
[1:19:14] anyway so you wouldn't really need to
[1:19:17] hook into the laravel aspect there i
[1:19:19] would just rely on the container
[1:19:20] scheduling
[1:19:21] to go hey i don't really want you
[1:19:22] consuming 14 giga ram so i'm going to
[1:19:24] restart you know
[1:19:26] okay that's cool so that's his job
[1:19:29] and what's the 500m that wasn't really
[1:19:31] covered earlier i guess
[1:19:32] it wasn't you so a single cpu is broken
[1:19:36] down into 1000 units
[1:19:38] and i think they're called millicourse
[1:19:40] so you can say this is essentially me
[1:19:42] saying that half a core
[1:19:43] this this process is restricted to half
[1:19:45] a core on the host machine
[1:19:47] does that does that translate to roughly
[1:19:50] like every one and two instructions
[1:19:52] like so if there's two pods on there
[1:19:55] both given half a core
[1:19:56] they will like sort of alternate who can
[1:19:59] get access
[1:20:00] or is what is that just like no so it
[1:20:03] depends on how many cores are available
[1:20:04] on the machine
[1:20:05] so like uh i'm not sure if i'm gonna be
[1:20:07] able to get that information from
[1:20:09] kubernetes here
[1:20:10] in fact uh let's see how permissive our
[1:20:14] thing is so
[1:20:18] containers don't necessarily obscure the
[1:20:20] view of the proc file system
[1:20:22] and so typically you can just pop in
[1:20:25] here
[1:20:27] and you'll still see the actual host
[1:20:28] information so you can see here i've got
[1:20:30] eight processors which means
[1:20:32] if i set this to
[1:20:36] 4000 m
[1:20:40] and scale this we've got it set on five
[1:20:43] yeah we won't see all five of those
[1:20:45] scheduled we should see that fail
[1:20:47] so
[1:20:53] yeah there we go we we have pending
[1:20:56] queue workers
[1:20:56] and if i describe one of those it'll
[1:21:00] tell me
[1:21:01] that the resources aren't available and
[1:21:03] sufficient cpu
[1:21:05] okay right so not it's not like
[1:21:09] um how it allocates it so well it's
[1:21:12] because we're using a limit right
[1:21:13] i mean i could have said uh
[1:21:18] requests which means i kind of want this
[1:21:22] but it's not a hard request you know if
[1:21:24] it's available give me it
[1:21:25] and whereas a limit is like it's
[1:21:27] actually going to set aside
[1:21:28] half a quart for that process and it's
[1:21:31] going to set aside 50 mega ram for that
[1:21:33] process
[1:21:33] and it won't allow me to schedule so
[1:21:36] there's still contention
[1:21:38] for any pods are running on the machine
[1:21:40] they're still competing for resources
[1:21:41] depending on the instructions they're
[1:21:42] sending
[1:21:43] but the scheduler is going to go i know
[1:21:45] at some point this is going to have
[1:21:48] 4 000 millicourse of cpu and i'm not
[1:21:50] going to schedule anything that tries to
[1:21:51] go beyond that
[1:21:52] whereas if i leave this as requests we
[1:21:55] should see
[1:21:56] that it just i think it will actually
[1:21:58] schedule most of them
[1:22:01] because they're not using that menu at
[1:22:03] that time
[1:22:05] oh no ash okay so the schedule is gonna
[1:22:07] say no as well all right
[1:22:09] so but yeah the request is kind of
[1:22:11] giving the scheduler a hint of what you
[1:22:13] need
[1:22:13] the limits means restart the process if
[1:22:15] it ever goes beyond it
[1:22:17] and then the scheduler will do its best
[1:22:18] to make sure you get scheduled on the
[1:22:20] nodes where it's not going to have too
[1:22:21] much contention for those resources
[1:22:23] okay yeah that makes sense okay that is
[1:22:28] actually too bad everything apart from
[1:22:31] one thing on my list
[1:22:33] pretty much so what did we not cover
[1:22:37] um release cycle so how would you might
[1:22:40] go about doing a natural like
[1:22:41] full-on release not necessarily with
[1:22:43] like ci and stuff but you build a new
[1:22:45] image it needs to be deployed
[1:22:46] do you go in with cube ctl delete the
[1:22:49] pubs
[1:22:50] how would you want to make that last i
[1:22:52] think no i mean it'll handle it for you
[1:22:54] so let's assume
[1:22:56] and we can do this in two minutes
[1:22:59] so uh yeah let's use our q worker right
[1:23:02] um so firstly let's just remove these
[1:23:05] limits um
[1:23:06] so we can get all five and let's change
[1:23:08] the image let's say
[1:23:09] instead of you know normally we would
[1:23:10] change the tag here to be v
[1:23:13] 54 or whatever right but what if i just
[1:23:15] want to say deploy
[1:23:16] engine x so the way that this works
[1:23:19] is if i just deploy this and run this
[1:23:22] really quickly
[1:23:23] is it oh container errors
[1:23:27] let's just take off all this stuff that
[1:23:28] we don't need the security context is
[1:23:30] why that's failing uh
[1:23:34] and the command won't exist but there's
[1:23:36] a whole lot of why that was failing
[1:23:37] so uh
[1:23:41] that's what i get for trying to do it
[1:23:42] too quickly right okay that's
[1:23:44] pretty generic so let's reapply that and
[1:23:47] then run this
[1:23:48] but what we're going to see is that and
[1:23:51] it's
[1:23:51] it's fast so it's difficult right but we
[1:23:54] actually spun up
[1:23:56] two new ones before shutting down the
[1:23:57] first one then we spun up a third and
[1:23:59] then we started scheduling two more
[1:24:00] after that and then it starts
[1:24:02] terminating
[1:24:03] so on top of a deployment object you
[1:24:05] actually have the ability to specify
[1:24:07] the the strategy
[1:24:11] and then we can have a type and a ruling
[1:24:15] update
[1:24:17] rolling update which allows us to
[1:24:19] specify a search
[1:24:21] or a max of unavailable so the
[1:24:24] deployment already knows how to do
[1:24:26] safe deploys with new images you have to
[1:24:28] tell it to do the rolling update which
[1:24:30] is
[1:24:30] actually happens by default and you get
[1:24:32] a max surge of
[1:24:34] one i think um you can also use
[1:24:37] percentages
[1:24:38] so you could say that i want 25 of my
[1:24:40] pods to be unavailable that means that
[1:24:42] it will sacrifice let's assume sorry
[1:24:45] lots of information
[1:24:47] let's assume i have 10 pods running if i
[1:24:49] have a max unavailable 25
[1:24:51] it's going to be able to shut down 25 of
[1:24:53] those pods which is
[1:24:54] two if it was 50 it would shut down five
[1:24:57] and then it would spin up new ones
[1:24:59] if we go with a surge approach what we
[1:25:01] say is i have 10
[1:25:03] with a max surge of 50 i'll actually
[1:25:04] schedule up to 15
[1:25:06] and then once five are healthy shut down
[1:25:08] five and then spin up more
[1:25:10] okay so in combination
[1:25:13] will you use one or the other you can
[1:25:15] only use one another so you can
[1:25:17] let's let's double check right because
[1:25:19] i've been wrong a few times a day anyway
[1:25:20] but
[1:25:22] oh it doesn't care okay i guess you can
[1:25:24] use them both together i thought you
[1:25:25] could only pick one so yeah here i could
[1:25:27] say
[1:25:27] i i always need at least 75
[1:25:30] to be running and i don't mind
[1:25:32] scheduling over provisioning by 50
[1:25:34] and then the scheduler will work it all
[1:25:35] out for you you don't need to worry
[1:25:37] about it too much
[1:25:38] okay okay so in terms of
[1:25:41] um when when you do a release you'd
[1:25:44] normally have
[1:25:44] a um your deployment process your ci or
[1:25:49] whatever would
[1:25:50] tag a new version of the image and then
[1:25:53] would you
[1:25:54] do like a cube apply a cube ctl apply
[1:25:58] and that would then start pulling in the
[1:25:59] new images for you it's definitely how
[1:26:01] i would start my you know my continuous
[1:26:04] integration deployment server would
[1:26:06] just reply over the top with that new
[1:26:08] tag
[1:26:09] or sha whatever i'm using and let
[1:26:10] kubernetes head up from there and then
[1:26:12] eventually you can start to look at
[1:26:13] things like
[1:26:14] you know get ops continuous deployment
[1:26:16] from within the cluster
[1:26:18] and get a little bit more sophisticated
[1:26:19] doing progressive rollouts making sure
[1:26:21] that
[1:26:22] you know the metrics don't change for
[1:26:23] the first 10 minutes at 10
[1:26:25] traffic and then scaling up we could do
[1:26:27] a couple of more episodes than that i'm
[1:26:29] not going to be able to do it justice
[1:26:30] in like 10 seconds but yeah yeah you
[1:26:33] could definitely start with a cube
[1:26:34] control apply
[1:26:35] and then take it from there okay that's
[1:26:37] something all right
[1:26:39] i think so yeah we covered it a lot so
[1:26:42] what i'll suggest is i hope people find
[1:26:44] this useful leave comments for anything
[1:26:45] that you want us to tackle in a future
[1:26:47] episode i'm sure alex would be happy to
[1:26:48] join me
[1:26:49] alex and i'll have our own conversations
[1:26:51] and work out what else we can do in the
[1:26:52] future we definitely
[1:26:54] already got an idea above which you'll
[1:26:55] probably hate me for so we'll cover that
[1:26:57] outside of the screen all right well
[1:27:00] thank you for joining me alex it was an
[1:27:01] absolute pleasure i had fun doing that
[1:27:03] i'll see you for the next one
[1:27:04] goodbye everyone cheers
[1:27:29] [Music]
[1:27:39] you
⚡ Saved you time reading this? Transcribe any YouTube video for free — no signup needed.