{"id":1093,"date":"2021-04-19T10:00:46","date_gmt":"2021-04-19T08:00:46","guid":{"rendered":"https:\/\/devpath.pro\/?p=1093"},"modified":"2021-04-19T10:00:46","modified_gmt":"2021-04-19T08:00:46","slug":"save-yourself-from-a-disaster-5-redundancy-of-web-servers","status":"publish","type":"post","link":"https:\/\/fabiocicerchia.it\/web\/save-yourself-from-a-disaster-5-redundancy-of-web-servers","title":{"rendered":"Save yourself from a disaster #5: Redundancy of Web Servers"},"content":{"rendered":"
This is the fifth part of the series Save yourself from a disaster: Redundancy on a budget<\/a>.<\/p>\n How can we make sure our second most important asset is safely secured in case of a disaster?<\/p>\n We could mainly 3 things:<\/p>\n <\/p>\n Nowadays many cloud providers (also virtualization platforms) are giving you the possibility to take a snapshot of the VM and then restore\/clone it. I’ll not cover it in this tutorial as we’ll increase the overall cost of the infrastructure. Although, sometimes (based on the application) it can be very time-saving doing a clone of the VM compared to the other method I’m proposing here below.<\/p>\n We live in 2021, everyone is running containers and wishing to have a k8s cluster to play with. So, let’s convert the simple applications into containers, there are a lot of already-ready containers on Docker Hub.<\/a><\/p>\n Docker Swarm<\/strong><\/p>\n Let’s start nice and easy, with Docker Swarm<\/a> (which eliminates the extra complexity of Kubernetes) on ONE node (then we can scale out<\/a> as much as we like).<\/p>\n First, setup your nodes<\/a>, I’m going to use standard images for my dockerized infrastructure, no custom images (for now – I’ve got pretty simple configurations). I’ve picked bitnami images<\/a>, as they cover a lot of scenarios and provide pre-packaged images for most of the popular server software (more reasons why pick them<\/a>).<\/p>\n If you really want to start using custom images you could publish them publicly for free on Docker Hub (but has got recently some limitations<\/a>) or on Canister<\/a>. After the announcement from Docker Hub about limiting the rates of pull, AWS decided to offer public repositories<\/a> (and they are almost free<\/a> if you don’t exceed 500GB\/month when not logged or 5TB\/month when logged).<\/p>\n Docker Compose<\/strong><\/p>\n This is an example of a WordPress website configured with docker-compose:<\/p>\n Ingress<\/strong><\/p>\n When using Docker Swarm with lots of containers and services (which bounds a dedicated port), you’ll need an ingress system to sort the requests to the right service. You could use one of the 2 most used solutions: Nginx<\/a> or Traefik<\/a>. TLS Termination<\/strong><\/p>\n This is the tricky part. If you have already bought the certificates (eg. from SSLs<\/a>) you’re good for 1 year (at least). If you don’t want to buy them and want to rely on Let’s Encrypt<\/a>, you’ll need to be ready to sweat a bit to set it up. Setting it up on one node is pretty simple, but if you need to replicate it on multiple nodes then you need to start being creative<\/a>.<\/p>\n One proposed solution would be having a primary node that generates (or renews) the certificate(s) and then it’ll spread them to the other servers:<\/p>\n Kubernetes is more complex and require more time to configure it, but once done there could be no vendor lock-in for you (as many providers are offering managed k8s), also it is more extensible (but more complex than swarm).<\/span><\/p>\n If you have already a Docker Swarm cluster and want to migrate try following these guides:<\/p>\n Remember to either use a dockerized database or rely on cloud-native managed solutions.\u00a0<\/span><\/p>\n The next post will be about Redundancy of DNS, Stay Tuned.<\/p>\n Check out the whole version of this post in the ebook. This is the fifth part of the series Save yourself from a disaster: Redundancy on a budget. How can we make sure our second most important asset is safely secured in case of a disaster? We could mainly 3 things: Duplicate VM Docker Kubernetes<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"advgb_blocks_editor_width":"","advgb_blocks_columns_visual_guide":"","footnotes":""},"categories":[14],"tags":[122,123,124,125],"aioseo_notices":[],"author_meta":{"display_name":"fabio","author_link":"https:\/\/fabiocicerchia.it\/author\/fabio"},"featured_img":null,"coauthors":[],"tax_additional":{"categories":{"linked":["Web<\/a>"],"unlinked":["Web<\/span>"]},"tags":{"linked":["disaster recovery<\/a>","ovh<\/a>","redundancy<\/a>","sbg2<\/a>"],"unlinked":["disaster recovery<\/span>","ovh<\/span>","redundancy<\/span>","sbg2<\/span>"]}},"comment_count":"0","relative_dates":{"created":"Posted 3 years ago","modified":"Updated 3 years ago"},"absolute_dates":{"created":"Posted on April 19, 2021","modified":"Updated on April 19, 2021"},"absolute_dates_time":{"created":"Posted on April 19, 2021 10:00 am","modified":"Updated on April 19, 2021 10:00 am"},"featured_img_caption":"","series_order":"","_links":{"self":[{"href":"https:\/\/fabiocicerchia.it\/wp-json\/wp\/v2\/posts\/1093"}],"collection":[{"href":"https:\/\/fabiocicerchia.it\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/fabiocicerchia.it\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/fabiocicerchia.it\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/fabiocicerchia.it\/wp-json\/wp\/v2\/comments?post=1093"}],"version-history":[{"count":0,"href":"https:\/\/fabiocicerchia.it\/wp-json\/wp\/v2\/posts\/1093\/revisions"}],"wp:attachment":[{"href":"https:\/\/fabiocicerchia.it\/wp-json\/wp\/v2\/media?parent=1093"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/fabiocicerchia.it\/wp-json\/wp\/v2\/categories?post=1093"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/fabiocicerchia.it\/wp-json\/wp\/v2\/tags?post=1093"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}\n
\nThis guide won’t cover everything, it won’t be a comprehensive guide, and the steps that are shown need to be carefully reviewed and tested in your development\/pre-production environment. I don’t take any responsibility for any damage, interruption of service nor leak\/loss of data for the use of the instructions in the ebook (nor from any external website I’ve mentioned).<\/small><\/div>\nDuplicate VM<\/h2>\n
Docker<\/h2>\n
version: \"3.9\"\n\nservices:\n wordpress:\n image: wordpress:5.7.0\n ports:\n - 8000:80\n deploy:\n replicas: 1\n restart_policy:\n condition: on-failure\n extra_hosts:\n - \"host.docker.internal:host-gateway\"\n environment:\n WORDPRESS_DB_HOST: host.docker.internal:3306\n WORDPRESS_DB_USER: ***\n WORDPRESS_DB_PASSWORD: ***\n WORDPRESS_DB_NAME: ***\n volumes:\n - \/path\/to\/wp-content:\/var\/www\/html\/wp-content\n healthcheck:\n test: [\"CMD\", \"curl\", \"-f\", \"http:\/\/localhost\"]\n interval: 30s\n timeout: 10s\n retries: 3\n<\/pre>\n
\nI decided to use a simple bitnami\/nginx<\/a> with a custom config (pretty straightforward proxy<\/a>):<\/p>\nversion: \"3.9\"\n\nservices:\n client:\n image: bitnami\/nginx:1.19.8\n ports:\n - 80:8080\n - 443:8443\n deploy:\n replicas: 2\n restart_policy:\n condition: on-failure\n extra_hosts:\n - \"host.docker.internal:host-gateway\"\n volumes:\n - \/root\/docker-compose\/nginx\/lb.conf:\/opt\/bitnami\/nginx\/conf\/server_blocks\/lb.conf:ro\n - \/etc\/letsencrypt:\/etc\/letsencrypt\n<\/pre>\n
rsync -e \"ssh -i $HOME\/.ssh\/somekey\" -auv --progress \/etc\/letsencrypt\/ syncerssl@<IP2>:\/etc\/letsencrypt\nrsync -e \"ssh -i $HOME\/.ssh\/somekey\" -auv --progress \/etc\/letsencrypt\/ syncerssl@<IP3>:\/etc\/letsencrypt\n<\/pre>\n
Kubernetes<\/h2>\n
\n
\n
\n<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"