|
| 1 | +# Immutable-webapp |
| 2 | +En implementasjon av stukturen fra https://immutablewebapps.org/ . |
| 3 | + |
| 4 | +[Slides](https://docs.google.com/presentation/d/1gcnwG0NzTiAlQ9NrjWCTa6c0yCiKYEkowBLn9BSKbjA/present) |
| 5 | + |
| 6 | +## Bli kjent |
| 7 | + |
| 8 | +### Om appen |
| 9 | + |
| 10 | +### Lokal oppstart |
| 11 | + |
| 12 | +* Kjør opp appen med `npm install && npm run start` |
| 13 | +* Generer en index.html med `node src-index/main.js` |
| 14 | +* Gjør deg kjent med hvor de forskjellige inputene og env-variablene i appen kommer fra |
| 15 | + |
| 16 | +## Min første immutable webapp |
| 17 | + |
| 18 | +Felles mål her er en immutable webapp med to S3-buckets og et CDN foran som hoster index.html og kildekode. |
| 19 | + |
| 20 | +Nyttige lenker: |
| 21 | +* Om du ikke er veldig kjent i aws-konsollen fra før, anbefaler jeg å sjekke ut de forskjellige servicene |
| 22 | +underveise |
| 23 | + - https://console.aws.amazon.com/s3 |
| 24 | + - https://console.aws.amazon.com/cloudfront |
| 25 | + - https://console.aws.amazon.com/route53 |
| 26 | +* [Terraform-docs](https://www.terraform.io/docs/providers/aws/r/s3_bucket.html) |
| 27 | +* [AWS-cli-docs](https://docs.aws.amazon.com/cli/latest/reference/s3/cp.html) |
| 28 | + |
| 29 | + |
| 30 | +### Testmiljø med buckets |
| 31 | + |
| 32 | +Opprett to [buckets](https://www.terraform.io/docs/providers/aws/r/s3_bucket.html) med terraform som skal bli der vi server asset og host. Start i `terraform/test/main.tf`. Husk at S3-bucketnavn må være unike innenfor en region! |
| 33 | + |
| 34 | +Anbefalt terraform-output for begge buckets: |
| 35 | +* bucket_domain_name - denne lenken kan du bruke til å aksessere filene du har lastet opp |
| 36 | +* id - navnet på bucketen du har opprettet |
| 37 | + |
| 38 | +Når begge bucket er oppprettet uten mer oppsett, og du kan gå inn i konsollen på web og manuelt laste opp en tilfeldig fil. Den vil ikke tilgjengelig på internett via `bucket_domain_name/filnavn`, ettersom default-policyen er at bucket er private. Vi kan konfigurere public tilgang ved å bruke acl-parameteret på en bucket eller en bucket policy. Sistnevnte er anbefalt av AWS ettersom bucketacl er et eldre og skjørere konsept. |
| 39 | + |
| 40 | +Opprett bucketpolicies for begge bøttene ved å bruke [`aws_s3_bucket_policy`](https://www.terraform.io/docs/providers/aws/r/s3_bucket_policy.html). I policy-atributtet kan du bruke en [templatefile](https://www.terraform.io/docs/configuration/functions/templatefile.html) med fila `policy/public_bucket.json.tpl`. Denne trenger en variabel `bucket_arn`. Bruk atributtet fra bucketen for å sende inn rett arn. |
| 41 | + |
| 42 | +Se [policy.md](terraform/test/policy/policy.md) for en forklaring på innholdet i policyen. |
| 43 | + |
| 44 | + |
| 45 | +### Bruke AWS-cliet til opplasting av filer |
| 46 | + |
| 47 | +Bygg assets lokalt med `npm run build` og bruk aws-cliet til å laste opp alt innholdet i build-mappen til asset-bucketen under navnet `assets/id`. Velg en tilfeldig id for testen, senere skal vi bruke githash! Test at fila blir tilgjengelig i browseren på `<bucket_domain_name>/assets/id/main.js` og sett rett cachcontrol-headers. |
| 48 | + |
| 49 | + |
| 50 | +`aws s3 cp <LocalPath> <S3Uri>` |
| 51 | + |
| 52 | +Se [AWS-cli-docs](https://docs.aws.amazon.com/cli/latest/reference/s3/cp.html) for `aws s3 cp` |
| 53 | + |
| 54 | +<details><summary>Tips</summary> |
| 55 | +<p> |
| 56 | + |
| 57 | +- bruk følgende S3-uri `s3://bucket-name/assets/1/` |
| 58 | +- `--recursive` laster opp hele mappen |
| 59 | +- `--cache-control public,max-age=31536000,immutable` setter cache-controls-headerne til alltid lagre som beskrevet i https://immutablewebapps.org/ |
| 60 | +</p> |
| 61 | +</details> |
| 62 | + |
| 63 | +Gjør endringer i `sha` og `url` i `src-index/main.js` for å peke på bucket og fila du har lastet opp over. |
| 64 | +Bygg index.html (`node src-index/main.js`) og bruk `aws s3 cp` igjen for å kopiere index.html til host-bucket. Husk rett headers |
| 65 | + |
| 66 | +Om du nå går på `<bucket_domain_name>/index.html` bør du se en kjørende applikasjon. |
| 67 | + |
| 68 | +<details><summary>Tips</summary> |
| 69 | +<p> |
| 70 | + |
| 71 | +- Bruk `index.html` både som localPath og `s3://bucket-host-name/index.html` som S3Uri ettersom vi kun laster opp en fil |
| 72 | +- `--cache-control no-store` setter cache-controls-headerne til aldri lagre som beskrevet i https://immutablewebapps.org/ |
| 73 | +</p> |
| 74 | +</details> |
| 75 | + |
| 76 | + |
| 77 | +### Autodeploy av assets med Github Actions |
| 78 | + |
| 79 | +Nå skal vi la Github Actions overta bygging av assets og opplasting til assets-bucketen under unike versjonsnavn. |
| 80 | +For enkelhets skyld er versjonsnavnet her `assets/sha/`. Vi skal bruke de samme kommandoene som over, |
| 81 | +men la det utførest av github. |
| 82 | + |
| 83 | +- I `.github/workflows/nodejs.yml` er det starten på en workflow. Fullfør denne slik at bygg og kopier filer til assets-bucketen skjer på hver push. |
| 84 | +- I run-delen av en githubaction kan man hente ut commit med `${{github.sha}}`, se [docs](https://help.github.com/en/actions/reference/contexts-and-expression-syntax-for-github-actions) |
| 85 | + |
| 86 | +Det finnes en githook som linter yml-filer for å slippe unna enkelte yml-feil i workflow-definisjonen. |
| 87 | +Om du ønsker å ta den i bruk kan du kjøre kommandoen `git config core.hooksPath .githooks` |
| 88 | + |
| 89 | + |
| 90 | +### Autodeploy til host |
| 91 | +- Utvid `.github/workflows/nodejs.yml` til også å generere og laste opp index.html i host-bucketen. Sjekk ut tilgjengelige variable for node i [docs](https://help.github.com/en/actions/configuring-and-managing-workflows/using-environment-variables). |
| 92 | + |
| 93 | + |
| 94 | +### CDN |
| 95 | + |
| 96 | +AWS CloudFront er Amazon sin CDN-provider, se [terraform-docs](https://www.terraform.io/docs/providers/aws/r/cloudfront_distribution.html). |
| 97 | +Om du gjør dette for første gang anbefaler jeg at du starter med et cloudfront-domene og heller endrer til eget domene i neste steg. |
| 98 | + |
| 99 | +For å mappe terraform-input til rett verdier, anbefaler jeg å se i aws-konsollen på CloudFront og velge "Create a distribution". |
| 100 | +En gotcha som er fin å vite om, dersom du [ikke setter verdier i ttl-atributtene](https://github.com/terraform-providers/terraform-provider-aws/issues/1994) til terraform vil dette gjøre at CloudFront velger å bruker cachecontrol-headers fra origin, tilsvarende `Use Origin Cache Headers` fra AWS-console'en. |
| 101 | + |
| 102 | +Figuren bakerst i slidesettet gir en slags oversikt av hvordan CloudFront passer inn som server for både host og assets - men dette var også den vanskeligste delen av oppgaven å beskrive! Så vær så snill å stikk innom Tine eller andre om det ikke gir mening. |
| 103 | + |
| 104 | +Test ut endringer i `App.jsx` og deploy ny versjon av assets og index for å sjekke caching og endringer. |
| 105 | +- OBS: Nå kan du bruke `domain_name` outputen fra cloudfront som erstatning for `my-url` i `src-index/main.js` |
| 106 | + |
| 107 | +<details><summary>Tips</summary> |
| 108 | +<p> |
| 109 | +- du trenger en `origin` pr. s3 bucket |
| 110 | +- `enabled`, `restrictions`, `viewer_certificate` kan være default |
| 111 | +- `default_root_object` er `index.html` |
| 112 | +- `default_cache_behavior` og `ordered_cache_behavior` kan ha like configparameter, men default må peke på host-bucket og ordered_cache_behavior på assets. Path `assets/*` matcher url-strukturen fra index.html |
| 113 | +</p> |
| 114 | +</details> |
| 115 | + |
| 116 | + |
| 117 | +## Alternativer videre (bruk rekkefølgen som står eller plukk selv om du ønsker noe spesielt) |
| 118 | + |
| 119 | +Cirka frem til punktet "Lag et eget domene" kan du finne et løsningsforslag i repoet https://github.com/kleivane/immutable-webapp . |
| 120 | + |
| 121 | +* Lag et prodmiljø |
| 122 | +* La terraform opprette en [iam-bruker](https://www.terraform.io/docs/providers/aws/r/iam_user.html) som bruker av github med rettigheter kun til opplasting i buckets. [Rettighetssimulatoren](http://awspolicygen.s3.amazonaws.com/policygen.html) for iam kan hjelpe litt |
| 123 | +* Ta i bruk remote [backend i S3 ](https://www.terraform.io/docs/backends/types/s3.html) |
| 124 | +* Trekk ut til en felles terraform-modul |
| 125 | +* Trekk ut bygging av index.html til en lambda |
| 126 | + * Lambdaen trenger kildekode i egen bucket |
| 127 | + * La tagging i github `lambda-x.y.z` trigge bygging og release av ny kildekode |
| 128 | + * Provisjoner lambda med terraform pr miljø og send inn versjon av kildekoden som skal brukes |
| 129 | +* Lag et eget domene i Route 53 slik at du har en egen url |
| 130 | + * Lag sertifikat fra certification manager |
| 131 | + * Legg inn alias og sertifikat (`viewer_certificate`) i cloudfront. Merk av `ssl_support_method = sni-only` for å unngå ekstra kostnader! |
| 132 | + * Opprett alias i route53 med en ny [record](https://www.terraform.io/docs/providers/aws/r/route53_record.html) |
| 133 | + * *Alias record typically have a type of A or AAAA, but they work like a CNAME record* |
| 134 | +* Ta i bruk https://github.com/nektos/act for kjøring av github-actions lokalt |
| 135 | +* Skriv tester! https://terratest.gruntwork.io/ |
| 136 | +* Trekk ut prodmiljø i en egen AWS-account |
| 137 | +* Rull ut dockercontaineren fra https://github.com/kleivane/static-json |
| 138 | +* Test ut [workspaces](https://www.terraform.io/docs/state/workspaces.html) for terraform-endringer |
| 139 | +* Bruk moduler fra https://github.com/cloudposse/, feks https://github.com/cloudposse/terraform-aws-cloudfront-cdn |
| 140 | +* Flytt cachecontrol fra hver enkelt fil til lambda@edge |
| 141 | +* Bruk en annen skyprovider |
0 commit comments