Nextcloud: Penerapan Toleransi Kesalahan untuk Perusahaan Menengah





Ada pemanen yang sangat keren untuk manajemen proyek bersama, otorisasi LDAP, sinkronisasi file dengan versi dan sesuatu seperti utusan perusahaan dengan konferensi video, yang dikacaukan di versi terbaru. Ya, saya sedang berbicara tentang Nextcloud. Di satu sisi, saya adalah pendukung Unix-way dan pembagian aplikasi yang jelas menjadi fungsi yang terpisah. Di sisi lain, produk ini lebih dari stabil, telah bekerja selama bertahun-tahun di beberapa proyek tanpa masalah dan peluit tambahan tidak mengganggu pekerjaannya. Jika Anda benar-benar ingin, Anda dapat mengacaukan hampir semua permainan di sana. Komunitas aktif dan sepenuhnya melengkapi berbagai plugin yang tersedia sebagai aplikasi terpisah.



Hari ini kami akan menerapkannya. Saya tidak akan memberikan instruksi langkah demi langkah yang lengkap, tetapi saya akan mencoba menyebutkan poin-poin penting dari arsitektur yang patut diperhatikan. Secara khusus, kami akan menganalisis load balancing, replikasi database, dan pemeliharaan rutin tanpa gangguan layanan.



Kami akan menerapkan dalam versi aman-gagal untuk perusahaan kecil dengan 150-1000 pengguna, tetapi ini juga akan berguna untuk pengguna rumahan.



Apa yang dibutuhkan perusahaan?



Perbedaan utama antara layanan pada server rumah yang nyaman yang terbuat dari biji pohon ek dan korek api dari segmen korporat adalah tanggung jawabnya kepada pengguna. Namun, bahkan di instalasi rumah saya, saya menganggapnya sebagai bentuk yang baik untuk mengirim pesan ke pengguna dengan peringatan tentang pekerjaan yang direncanakan atau kemungkinan kecelakaan. Lagi pula, pada Sabtu malam teman Anda mungkin tiba-tiba memutuskan untuk bekerja dengan data yang dia host dengan Anda.



Dalam kasus perusahaan, bahkan yang kecil, layanan penting yang sederhana berarti potensi kerugian dan masalah. Apalagi jika ada banyak proses yang terlibat dalam layanan.



Secara khusus, menurut pengalaman saya, Nextcloud membutuhkan beberapa fitur di antara perusahaan kecil:



  1. Menyediakan akses ke direktori bersama dan sinkronisasi.
  2. Fitur mematikan dengan penyediaan akses eksternal dalam federasi. Anda dapat berintegrasi dengan produk serupa dari kolega dan perusahaan lain.
  3. Memberikan akses eksternal melalui tautan langsung. Ini sangat membantu jika Anda, misalnya, bekerja di industri percetakan dan perlu bertukar data berat dalam jumlah besar dengan klien.
  4. Editor dokumen Collabora yang berjalan di sisi server dan bertindak sebagai antarmuka untuk LibreOffice.
  5. Obrolan dan panggilan video. Fitur yang sedikit kontroversial, tidak sepenuhnya stabil, tetapi ada dan berfungsi. Di versi terbaru, itu sudah distabilkan.


Kami membangun arsitektur



Sayangnya, di versi terbaru, dokumentasi Nextcloud Enterprise Implementation hanya tersedia untuk anggota berbayar. Namun, sebagai referensi, Anda dapat mengambil manual lama yang masih dalam domain publik.





Khas untuk penggunaan di rumah dan instalasi tunggal.



Opsi "all-in-one" tidak buruk selama Anda memiliki sedikit pengguna dan Anda dapat membayar waktu henti untuk pemeliharaan rutin. Misalnya, selama pembaruan. Juga, skema monolitik dengan penempatan pada satu node memiliki masalah dengan penskalaan. Karena itu, kami akan mencoba opsi kedua.





Opsi penerapan yang skalabel direkomendasikan untuk beban kerja yang lebih tinggi.



Komponen utama sistem:



  • 1 Penyeimbang. Anda dapat menggunakan HAproxy atau Nginx. Saya akan mempertimbangkan opsi dengan Nginx.
  • 2-4 buah Application server (web-server). Penginstalan Nextcloud sendiri dengan kode utama di php.
  • 2 DB. Dalam konfigurasi standar yang disarankan, ini adalah MariaDB.
  • Penyimpanan NFS.
  • Redis untuk menyimpan kueri database


Pengimbang



Dengan arsitektur ini, Anda akan memiliki lebih sedikit titik kegagalan. Titik utama kegagalan adalah penyeimbang beban. Jika tidak tersedia, pengguna tidak akan dapat menjangkau layanan tersebut. Untungnya, konfigurasi nginx yang sama cukup sederhana, seperti yang akan kita bahas lebih lanjut, dan ia menahan beban tanpa masalah. Sebagian besar kegagalan pada penyeimbang diselesaikan dengan memulai ulang daemon, seluruh node, atau menerapkan dari cadangan. Tidak akan berlebihan jika memiliki cadangan dingin yang dikonfigurasi di lokasi lain dengan lalu lintas manual yang beralih ke DNS tersebut.



Harap perhatikan bahwa penyeimbang juga merupakan titik terminasi SSL / TLS untuk klien Anda, dan komunikasi dengan backend dapat dilakukan melalui HTTP untuk jaringan internal tepercaya, atau dengan HTTPS tambahan jika lalu lintas ke server aplikasi melalui saluran umum yang tidak tepercaya.



Database



Solusi tipikal adalah MySQL / MariaDB dalam eksekusi berkerumun dalam replikasi master-slave. Pada saat yang sama, Anda hanya memiliki satu database aktif, dan yang kedua beroperasi dalam mode siaga panas jika terjadi kegagalan darurat database utama atau selama pekerjaan terjadwal. Penyeimbangan beban juga dapat dipertimbangkan, tetapi secara teknis lebih sulit. Saat menggunakan MariaDB Galera Cluster dengan opsi replikasi master-master, Anda perlu menggunakan node dalam jumlah ganjil, tetapi setidaknya tiga. Dengan demikian, risiko situasi otak terbelah diminimalkan, ketika konektivitas antar node terputus.



Penyimpanan



Solusi apa pun yang terbaik untuk Anda yang disediakan oleh protokol NFS. Untuk beban tinggi, pertimbangkan IBM Elastic Storage atau Ceph. Dimungkinkan juga untuk menggunakan penyimpanan objek yang kompatibel dengan S3, tetapi ini lebih merupakan opsi untuk instalasi yang sangat besar.



HDD atau SSD



Pada prinsipnya, untuk instalasi berukuran sedang, menggunakan HDD saja sudah cukup. Hambatan di sini adalah iops saat membaca dari database, yang sangat memengaruhi daya respons sistem, tetapi jika Anda memiliki Redis, yang menyimpan semua cache di RAM, ini tidak akan menjadi masalah besar. Selain itu, bagian dari cache akan disimpan dalam memcache di server aplikasi. Namun, saya akan merekomendasikan hosting server aplikasi pada SSD bila memungkinkan. Antarmuka web terasa jauh lebih responsif. Dalam kasus ini, sinkronisasi file yang sama pada klien desktop akan bekerja dengan cara yang kira-kira sama seperti saat menggunakan HDD untuk node ini.



Kecepatan sinkronisasi dan pengunggahan file akan ditentukan oleh kinerja penyimpanan NFS Anda.



Mengonfigurasi penyeimbang



Sebagai contoh, saya akan memberikan konfigurasi dasar yang sederhana dan nginx yang efektif. Ya, berbagai failover-bak tambahan hanya tersedia dalam versi berbayar, tetapi bahkan dalam versi dasar itu dengan sempurna memenuhi tugasnya. Harap dicatat bahwa round robin atau random balancing tidak cocok untuk kami, karena server aplikasi menyimpan cache untuk klien tertentu.

Untungnya, ini diselesaikan menggunakan metode ip_hash . Dalam kasus ini, sesi pengguna akan ditetapkan ke backend tertentu, tempat semua permintaan dari pengguna akan diarahkan. Poin ini dijelaskan dalam dokumentasi:

, IP- . IPv4- IPv6- . , . , . .


Sayangnya, saat menggunakan metode ini, mungkin ada masalah dengan pengguna yang berada di belakang IP dinamis dan terus mengubahnya. Misalnya, pada klien dengan Internet seluler, yang dapat dilemparkan di sepanjang rute yang berbeda saat beralih antar sel. cookie lengket yang memecahkan masalah ini hanya tersedia dalam versi berbayar.



File konfigurasi nginx menjelaskan ini sebagai berikut:



upstream backend {
    ip_hash;

    server backend1_nextcloud.example.com;
    server backend2_nextcloud.example.com;
    server backend3_nextcloud.example.com;
    server backend4_nextcloud.example.com;
}


Dalam kasus ini, beban akan didistribusikan secara merata di antara server aplikasi, meskipun ketidakseimbangan beban dapat terjadi karena klien terikat pada sesi tertentu. Untuk instalasi kecil hingga menengah, hal ini dapat diabaikan. Jika backend Anda memiliki daya yang berbeda, Anda dapat menyetel bobotnya masing-masing. Kemudian penyeimbang akan mencoba mendistribusikan beban secara proporsional dengan bobot yang diberikan:



upstream backend {
    ip_hash;

    server backend1_nextcloud.example.com weight=3;
    server backend2_nextcloud.example.com;
    server backend3_nextcloud.example.com;
}


Dalam contoh yang diberikan, dari 5 permintaan yang diterima, 3 akan pergi ke backend1, 1 ke backend2 dan 1 ke backend3.



Jika salah satu server aplikasi gagal, nginx akan mencoba mengalihkan permintaan ke server berikutnya dari daftar backend.



Konfigurasi database



Detail konfigurasi Master-Slave dapat ditemukan di dokumentasi utama .



Mari kita lihat beberapa poin penting. Pertama, kami membuat pengguna untuk replikasi data:



create user 'replicant'@'%' identified by 'replicant_password';
grant replication slave on *.* to replicant;
flush privileges;


Kemudian kami mengedit konfigurasi master:



sudo nano /etc/mysql/mariadb.conf.d/50-server.cnf 


Di area blok "Logging dan Replikasi", lakukan pengeditan yang diperlukan:



[mysqld]
log-bin         = /var/log/mysql/master-bin
log-bin-index   = /var/log/mysql/master-bin.index
binlog_format   = mixed
server-id       = 01
replicate-do-db = nextcloud
bind-address = 192.168.0.6


Di Slave, kami mengonfigurasi konfigurasi:



sudo nano /etc/mysql/mariadb.conf.d/50-server.cnf 


Di area blok "Logging dan Replikasi", lakukan pengeditan yang diperlukan:



    [mysqld]
    server-id       = 02
    relay-log-index = /var/log/mysql/slave-relay-bin.index
    relay-log       = /var/log/mysql/slave-relay-bin
    replicate-do-db = nextcloud
    read-only = 1
    bind-address    = 192.168.0.7


Mulai ulang kedua server:



sudo systemctl restart mariadb


Selanjutnya, Anda perlu menyalin database ke Slave.

Di Master, pertama-tama kami melakukan penguncian tabel:



flush tables with read lock;


Dan kemudian kami melihat statusnya:




    MariaDB [(none)]> show master status;
    +-------------------+----------+--------------+------------------+
    | File              | Position | Binlog_Do_DB | Binlog_Ignore_DB |
    +-------------------+----------+--------------+------------------+
    | master-bin.000001 |      772 |              |                  |
    +-------------------+----------+--------------+------------------+
    1 row in set (0.000 sec)


Jangan keluar dari konsol basis data, jika tidak, kunci akan dihapus!

Kita akan membutuhkan master_log_file dan master_log_pos dari sini untuk konfigurasi Slave.

Membuang dan melepas kunci:




sudo mysqldump -u root nextcloud > nextcloud.sql



    > unlock tables;
    > exit;


Kemudian kami mengimpor dump ke Slave dan memulai ulang daemon:




sudo mysqldump -u root nextcloud < nextcloud.sql
sudo systemctl restart mariadb


Setelah itu, siapkan replikasi di konsol:




    MariaDB [(none)]> change master 'master01' to     
    master_host='192.168.0.6',     
    master_user='replicant',     
    master_password='replicant_password',     
    master_port=3306,     
    master_log_file='master-bin.000001',     
    master_log_pos=772,     
    master_connect_retry=10,     
    master_use_gtid=slave_pos;


Kami meluncurkan dan memeriksa:




> start slave 'master01';
show slave 'master01' status\G;


Tidak boleh ada kesalahan dalam jawaban dan dua poin akan menunjukkan keberhasilan prosedur:



Slave_IO_Running: Yes
Slave_SQL_Running: Yes


Terapkan Node Aplikasi



Ada beberapa opsi penerapan:



  1. jepret
  2. buruh pelabuhan
  3. pembaruan manual


Snap tersedia terutama untuk Ubuntu. Ini cukup bagus dalam memberikan aplikasi berpemilik yang kompleks, tetapi secara default. Tetapi ia memiliki fitur yang agak mengganggu di lingkungan industri - ia secara otomatis memperbarui paketnya beberapa kali sehari. Anda juga harus melihat melalui akses tambahan ke luar jika Anda memiliki jaringan internal yang dibatasi secara kaku. Pada saat yang sama, mencerminkan repositori di dalamnya tidak sepenuhnya sepele.



Ya, ada saluran langganan, dan rilis utama, secara teori, itu tidak boleh beralih, tetapi pikirkanlah. Saya akan merekomendasikan kontrol penuh atas proses update, terutama karena sering kali disertai dengan perubahan struktur data di database.



Docker-image adalah pilihan yang bagus, terutama jika infrastruktur Anda sudah berjalan di Kubernetes. Node Redis yang sama kemungkinan akan pergi ke cluster setelah server aplikasi.



Jika Anda tidak memiliki infrastruktur untuk melakukan ini, maka memperbarui dan menerapkan secara manual dari tar.gz cukup nyaman dan dapat dikontrol.



Ingatlah bahwa Anda perlu menginstal server web di server aplikasi untuk menangani permintaan yang masuk. Saya akan merekomendasikan banyak nginx + php-fpm7.4. Dengan versi terbaru dari php-fmp, kinerja dan daya tanggap telah meningkat secara signifikan.



Mengonfigurasi SSL / TLS



Anda pasti harus mengandalkan TLS 1.3 jika Anda melakukan instalasi baru dan tidak ada masalah dengan paket nginx yang bergantung pada kesegaran sistem openssl. Secara khusus, 0-RTT dan barang lainnya terkadang memungkinkan untuk secara signifikan mempercepat koneksi ulang klien karena cache. Keamanan juga lebih tinggi karena memotong protokol yang sudah ketinggalan zaman.



Saya akan memberikan konfigurasi sebenarnya untuk server aplikasi nginx, yang berkomunikasi dengan penyeimbang melalui TLS:



Konfigurasi Nginx
upstream php-handler {
 server unix:/var/run/php/php7.4-fpm.sock;
}

server {
    listen 80;
    server_name backend1_nextcloud.example.com;
    # enforce https
    root /var/www/nextcloud/;
    return 301 https://$server_name$request_uri;
}

server {
    listen 443 ssl http2;
    ssl_early_data on;
#    listen [::]:443 ssl http2;
    server_name backend1_nextcloud.example.com;

    # Path to the root of your installation
    root /var/www/nextcloud/;
    # Log path
    access_log /var/log/nginx/nextcloud.nginx-access.log;
    error_log /var/log/nginx/nextcloud.nginx-error.log;
    ### SSL CONFIGURATION ###
        ssl_certificate /etc/letsencrypt/live/backend1_nextcloud.example.com/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/backend1_nextcloud.example.com/privkey.pem;
        ssl_trusted_certificate /etc/letsencrypt/live/backend1_nextcloud.example.com/fullchain.pem;
        ssl_dhparam /etc/ssl/certs/dhparam.pem;

        ssl_protocols TLSv1.2 TLSv1.3;
        ssl_prefer_server_ciphers on;
        #ssl_ciphers "EECDH+AESGCM:EECDH+CHACHA20:EECDH+AES256:!AES128";
        ssl_ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POL>
        ssl_session_cache shared:SSL:50m;
        ssl_session_timeout 5m;

        ssl_stapling on;
        ssl_stapling_verify on;
        resolver 8.8.4.4 8.8.8.8;

        add_header Strict-Transport-Security 'max-age=63072000; includeSubDomains; preload' always;
###   SSL ###

    # Add headers to serve security related headers
    # Before enabling Strict-Transport-Security headers please read into this
    # topic first.
    # add_header Strict-Transport-Security "max-age=15768000;
    # includeSubDomains; preload;";
    #
    # WARNING: Only add the preload option once you read about
    # the consequences in https://hstspreload.org/. This option
    # will add the domain to a hardcoded list that is shipped
    # in all major browsers and getting removed from this list
    # could take several months.
    add_header Referrer-Policy "no-referrer" always;
    add_header X-Content-Type-Options "nosniff" always;
    add_header X-Download-Options "noopen" always;
    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header X-Permitted-Cross-Domain-Policies "none" always;
    add_header X-Robots-Tag "none" always;
    add_header X-XSS-Protection "1; mode=block" always;

    # Remove X-Powered-By, which is an information leak
    fastcgi_hide_header X-Powered-By;

    location = /robots.txt {
        allow all;
        log_not_found off;
        access_log off;
    }

    # The following 2 rules are only needed for the user_webfinger app.
    # Uncomment it if you're planning to use this app.
    #rewrite ^/.well-known/host-meta /public.php?service=host-meta last;
    #rewrite ^/.well-known/host-meta.json /public.php?service=host-meta-json
    # last;

    location = /.well-known/carddav {
      return 301 $scheme://$host/remote.php/dav;
    }
    location = /.well-known/caldav {
      return 301 $scheme://$host/remote.php/dav;
    }

    # set max upload size
    client_max_body_size 512M;
    fastcgi_buffers 64 4K;

    # Enable gzip but do not remove ETag headers
    gzip on;
    gzip_vary on;
    gzip_comp_level 4;
    gzip_min_length 256;
    gzip_proxied expired no-cache no-store private no_last_modified no_etag auth;
    gzip_types application/atom+xml application/javascript application/json application/ld+json application/manifest+json application/rss+xml application/vnd.geo+json application/vnd.ms-fon>

    # Uncomment if your server is build with the ngx_pagespeed module
    # This module is currently not supported.
    #pagespeed off;

    location / {
        rewrite ^ /index.php;
    }

    location ~ ^\/(?:build|tests|config|lib|3rdparty|templates|data)\/ {
        deny all;
    }
location ~ ^\/(?:\.|autotest|occ|issue|indie|db_|console) {
        deny all;
    }

    location ~ ^\/(?:index|remote|public|cron|core\/ajax\/update|status|ocs\/v[12]|updater\/.+|oc[ms]-provider\/.+)\.php(?:$|\/) {
        fastcgi_split_path_info ^(.+?\.php)(\/.*|)$;
        set $path_info $fastcgi_path_info;
        try_files $fastcgi_script_name =404;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param PATH_INFO $path_info;
        fastcgi_param HTTPS on;
        # Avoid sending the security headers twice
        fastcgi_param modHeadersAvailable true;
        # Enable pretty urls
        fastcgi_param front_controller_active true;
        fastcgi_pass php-handler;
        fastcgi_intercept_errors on;
        fastcgi_request_buffering off;
    }

    location ~ ^\/(?:updater|oc[ms]-provider)(?:$|\/) {
        try_files $uri/ =404;
        index index.php;
    }

    # Adding the cache control header for js, css and map files
    # Make sure it is BELOW the PHP block
    location ~ \.(?:css|js|woff2?|svg|gif|map)$ {
        try_files $uri /index.php$request_uri;
        add_header Cache-Control "public, max-age=15778463";
        # Add headers to serve security related headers (It is intended to
        # have those duplicated to the ones above)
        # Before enabling Strict-Transport-Security headers please read into
        # this topic first.
        #add_header Strict-Transport-Security "max-age=15768000; includeSubDomains; preload;" always;
        #
        # WARNING: Only add the preload option once you read about
        # the consequences in https://hstspreload.org/. This option
        # will add the domain to a hardcoded list that is shipped
        # in all major browsers and getting removed from this list
        # could take several months.
        add_header Referrer-Policy "no-referrer" always;
        add_header X-Content-Type-Options "nosniff" always;
        add_header X-Download-Options "noopen" always;
        add_header X-Frame-Options "SAMEORIGIN" always;
        add_header X-Permitted-Cross-Domain-Policies "none" always;
        add_header X-Robots-Tag "none" always;
        add_header X-XSS-Protection "1; mode=block" always;

        # Optional: Don't log access to assets
        access_log off;
    }

    location ~ \.(?:png|html|ttf|ico|jpg|jpeg|bcmap)$ {
        try_files $uri /index.php$request_uri;
        # Optional: Don't log access to other assets
        access_log off;
    }
}


Perawatan rutin



Ingat, dalam lingkungan industri, Anda perlu menyediakan waktu henti minimal dan nol untuk peningkatan atau bahkan lebih banyak cadangan. Kesulitan utama di sini adalah ketergantungan status metadata dalam database dan file itu sendiri, yang tersedia melalui NFS atau penyimpanan objek.



Saat meningkatkan server aplikasi ke versi minor yang baru, tidak ada masalah khusus. Tetapi cluster masih perlu dipindahkan ke mode pemeliharaan untuk memperbarui struktur database.

Matikan penyeimbang pada saat beban paling sedikit dan lanjutkan dengan pembaruan.



Setelah itu, kami melakukan proses pembaruan manual dari tar.gz yang diunduh, sambil menyimpan file konfigurasi config.php. Memperbarui melalui web pada instalasi besar adalah ide yang sangat buruk!

Kami memperbarui melalui baris perintah:



sudo -u www-data php /var/www/nextcloud/occ upgrade


Setelah itu, nyalakan penyeimbang dan kirim lalu lintas ke server yang diperbarui. Untuk melakukan ini, kami menghapus semua server aplikasi yang tidak diperbarui dari penyeimbangan:



upstream backend {
    ip_hash;

    server backend1_nextcloud.example.com;
    server backend2_nextcloud.example.com down;
    server backend3_nextcloud.example.com down;
    server backend4_nextcloud.example.com down;
}


Node lainnya secara bertahap diperbarui dan dioperasikan. Dalam hal ini, peningkatan lanjutan tidak perlu dilakukan! Anda hanya perlu mengganti file php dan menyimpan konfigurasinya.



Saat mencadangkan, Anda harus menghentikan replikasi ke Slave dan melakukan dump metadata secara bersamaan dari database secara bersamaan dengan membuat snapshot file di penyimpanan. Anda perlu menyimpannya berpasangan. Pemulihan juga harus dilakukan dari dump database dan file untuk periode yang sama. Jika tidak, kehilangan data mungkin terjadi, karena file tersebut mungkin ada di penyimpanan, tetapi tidak memiliki metadata di database.










All Articles