TubeSum ← Transcribe a video

Laravel on Kubernetes: Into Production | Rawkode Live

Transcribed Jun 17, 2026 Watch on YouTube ↗
Intermediate 15 min read For: Laravel developers with basic Kubernetes knowledge looking to deploy applications in production.
8.8K
Views
168
Likes
16
Comments
9
Dislikes
2.1%
📈 Moderate

AI Summary

This 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.

[01:37]
Guest Introduction

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.

[02:52]
Example Application Overview

The example application includes jobs, email sending, queue tasks, scheduled tasks, and asset compilation, designed to test infrastructure components.

[12:00]
Deploying MariaDB

They deploy MariaDB on Kubernetes using a simple Deployment and Service, setting environment variables for the database user and password.

[35:13]
ConfigMaps and Secrets

They create a ConfigMap for environment variables and a Secret for the app key, explaining the difference and best practices for secrets management.

[61:25]
Database Migrations with Init Containers

They use an init container to run `php artisan migrate --force` before the main application starts, ensuring migrations run once per deployment.

[70:40]
Scheduled Tasks with CronJob

They create a CronJob to run `php artisan schedule:run` every minute, replacing traditional cron for Laravel's scheduler.

[75:00]
Queue Workers Deployment

They deploy queue workers as a separate Deployment running `php artisan queue:work`, allowing independent scaling and resource management.

[84:05]
Rolling Updates

They demonstrate a rolling update by changing the image tag and applying the deployment, showing how Kubernetes handles zero-downtime updates.

Clickbait Check

85% Legit

"The title accurately reflects the content, which focuses on deploying a Laravel application to Kubernetes with production considerations."

Mentioned in this Video

Tutorial Checklist

1 12:00 Create a Deployment and Service for MariaDB with environment variables for user, password, and database.
2 09:43 Build Docker images for PHP-FPM and Nginx, then push to a registry or use locally with imagePullPolicy: Never.
3 35:13 Create a ConfigMap for non-sensitive environment variables (e.g., DB_HOST, APP_NAME) and a Secret for sensitive values (e.g., APP_KEY).
4 14:00 Define a Deployment for the main application with two containers (nginx and fpm), mount emptyDir volumes for logs and cache, and set security context.
5 61:25 Add an init container to the Deployment that runs `php artisan migrate --force` to handle database migrations.
6 70:40 Create a CronJob resource that runs `php artisan schedule:run` every minute for scheduled tasks.
7 75:00 Create a separate Deployment for queue workers running `php artisan queue:work`, with its own resource limits and scaling.
8 84:05 Update the deployment manifest with a new image tag and apply it to trigger a rolling update.

Study Flashcards (10)

How do you run database migrations in a Kubernetes deployment?

medium Click to reveal answer

Use an init container that runs `php artisan migrate --force`.

61:25

How do you handle Laravel's scheduled tasks in Kubernetes?

medium Click to reveal answer

Use a CronJob resource that runs `php artisan schedule:run` every minute.

70:40

How do you deploy Laravel queue workers in Kubernetes?

medium Click to reveal answer

Use a Deployment with the command `php artisan queue:work`.

75:00

What Kubernetes resources are used to manage environment configuration?

easy Click to reveal answer

Use ConfigMaps for non-sensitive data and Secrets for sensitive data.

35:13

What tools can encrypt secrets before storing them in version control?

hard Click to reveal answer

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?

easy Click to reveal answer

Use a rolling update strategy, which is the default for Deployments.

84:05

What do `maxSurge` and `maxUnavailable` parameters control in a rolling update?

hard Click to reveal answer

`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?

easy Click to reveal answer

Set the image pull policy to `Never`.

20:54

How do you configure Laravel to log to standard output instead of a file?

medium Click to reveal answer

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?

medium Click to reveal answer

Use emptyDir volumes for ephemeral storage like logs and cache.

25:07

💡 Key Takeaways

🔧

Init Containers for Migrations

Shows a clean, Kubernetes-native way to run database migrations before the main application starts.

61:25
⚖️

CronJob for Scheduled Tasks

Demonstrates how to replace traditional cron with Kubernetes CronJob for Laravel's scheduler.

70:40
🔧

Queue Workers as Deployments

Explains why queue workers should be separate Deployments for scalability and resource management.

75:00
💡

Secrets Management Tools

Provides practical recommendations for encrypting secrets in version control.

58:27
📊

Rolling Update Defaults

Clarifies that Kubernetes Deployments use rolling updates by default for zero-downtime deployments.

84:05

✂️ Creator Tools: Viral Hooks

AI-generated clip ideas for Shorts based on the transcript

Laravel on Kubernetes: Missing Migrations

60s

Addresses a common pain point for developers deploying Laravel apps on Kubernetes, sparking engagement.

▶ Play Clip

Kubernetes Resource Limits Explained

54s

Offers a clear, practical explanation of resource constraints, a key concept for Kubernetes beginners.

▶ Play Clip

Fix Laravel Storage Permissions on K8s

60s

Shows a real-time debugging process for a common storage permission issue, highly educational for devs.

▶ Play Clip

Secrets vs ConfigMaps in Kubernetes

60s

Breaks down a confusing topic with clear examples, encouraging viewers to learn about security best practices.

▶ Play Clip

Running Laravel Migrations on Kubernetes

60s

Demonstrates a critical deployment step often overlooked, making it valuable for production-readiness.

▶ Play Clip

[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.