چرا فایلها را از دیسک اپلیکیشن جدا کنیم
container های اپلیکیشن باید بدونوضعیت باشند تا بتوان آنها را بدون از دست دادن آپلودهای کاربر دوباره deploy، مقیاس و rollback کرد. وقتی آواتارها، عکسهای محصول، فاکتورها و ویدئو روی فایلسیستم container نوشته میشوند، هر restart داده را به خطر میاندازد و هر replica مجموعه متفاوتی از فایلها دارد. Object Storage این را با دادن یک جای مشترک، بادوام و واحد به همه replica ها برای خواندن و نوشتن حل میکند. اپلیکیشن شما دورریختنی میماند در حالی که داده مستقل زندگی میکند.
واقعاً سازگار با S3، نه یک بدل
این سرویس API از نوع S3 را صحبت میکند، بنابراین ابزارهایی که پیشتر استفاده میکنید به کار خود ادامه میدهند: aws-cli، boto3، AWS SDK for JavaScript، درایورهای فایلسیستم S3 در Laravel و Symfony، rclone و s3cmd همه بهمحض تنظیم URL از نوع endpoint و جفت کلید با آن صحبت میکنند. آپلودهای multipart برای فایلهای بزرگ، متادیتای اشیا و رسیدگی به content-type آنطور رفتار میکنند که توسعهدهندگان S3 انتظار دارند. این یعنی مهاجرت یک اپلیکیشنی که پیشتر از S3 استفاده میکند معمولاً یک تغییر پیکربندی است نه بازنویسی کد.
bucket ها، access key ها و شعاع انفجار
داده را در bucket ها سازمان میدهید و دسترسی را با جفتهای access key ID و secret key کنترل میکنید که میتوانید هر زمان بچرخانید یا باطل کنید. نگه داشتن یک کلید بهازای هر اپلیکیشن یا هر bucket، شعاع انفجار را محدود میکند: اگر یک کلید در یک لاگ یا یک bundle کلاینت نشت کند، همان یک جفت را باطل و از نو تولید میکنید بدون دست زدن به هر سرویس دیگر. پنل فهرست میکند کدام کلیدها وجود دارند تا بتوانید کلیدهایی را که دیگر استفاده نمیشوند بازبینی و بازنشسته کنید.
ذخیرهسازی و CDN بهعنوان یک واحد
چون Object Storage و edge CDN همان پلتفرماند، میتوانید اشیای bucket را از طریق cache ارائه دهید بدون سیمکشی یک origin جداگانه. یک bucket عمومی یا یک مسیر edge امضاشده به یک مسیر دانلود سریع تبدیل میشود که در آن فایلهای پرطرفدار نزدیک کاربران cache میشوند و هرگز بهطور مکرر به ذخیرهسازی نمیزنند. وقتی یک فایل را زیر یک کلید موجود جایگزین میکنید، یک purge هدفمند از پنل یا cdnctl، edge را تازه میکند تا هیچکس نسخه کهنه دریافت نکند.
bind کردن ذخیرهسازی به اپلیکیشنهای container
بهجای چسباندن اعتبارنامهها در Dockerfile یا commit کردن آنها به یک مخزن، یک bucket را به یک Container App، bind میکنید و پلتفرم endpoint و کلیدها را بهعنوان متغیرهای محیطی، بهصورت اختیاری زیر یک پیشوند، تحویل میدهد تا چند bucket مجزا بمانند. کد شما نامهای استاندارد env را در زمان اجرا میخواند، secret ها هرگز در image ظاهر نمیشوند، و چرخاندن یک کلید بهجای وادار کردن به یک build مجدد، binding را بهروزرسانی میکند. این جدایی دوازدهعاملی پیکربندی از کد را دستنخورده نگه میدارد.
پشتیبانها و داده سرد
Object Storage خانهای طبیعی برای dump های دیتابیس، پشتیبانهای اپلیکیشن و export های بایگانی است که میخواهید از سرور اصلی جدا باشند اما همچنان بتوان آنها را سریع بازیابی کرد. چون دسترسی مبتنی بر کلید و محدود است، یک کار پشتیبانگیری میتواند یک کلید با گردشکار از نوع فقطنوشتن نگه دارد که جدا از کلیدهایی است که اپلیکیشن زنده شما استفاده میکند. با اسکریپت شدن از طریق cdnctl در یک کار شبانه، آپلودها و پاکسازیهای نگهداری بدون نظارت اجرا میشوند، و یک محدودیت مصرف روی bucket نگه میدارید تا بایگانیها بدون آنکه کسی متوجه شود رشد نکنند.
راهاندازی گامبهگام
یک bucket بسازید
در پنل بخش Object Storage را باز کنید و Create Bucket را انتخاب کنید. یک نام امن برای DNS به آن بدهید (حروف کوچک، اعداد و خط تیره) و تصمیم بگیرید که اشیا بهصورت پیشفرض خصوصی باشند یا عموماً قابلخواندن. خصوصی انتخاب درست برای پشتیبانها و نسخههای اصلی است که آنها را sign یا proxy خواهید کرد؛ خواندن عمومی برای داراییهایی مناسب است که قصد دارید مستقیماً از طریق CDN ارائه دهید.
یک جفت access key تولید کنید
تب Access Keys را باز کنید و یک کلید تولید کنید. یک access key ID و یک secret key میگیرید؛ secret تنها یکبار نمایش داده میشود، بنابراین بلافاصله آن را در secret manager خود کپی کنید. کلید را به bucket ای که به آن نیاز دارد محدود کنید بهجای استفاده مجدد از یک کلید master در سراسر هر پروژه، تا یک نشت با باطل کردن یک جفت کنترل شود.
یک کلاینت S3 را به endpoint اشاره دهید
هر SDK از نوع S3 یا aws-cli را با URL از نوع endpoint شبکه cdn.com.tr که در صفحه bucket نمایش داده میشود، آدرسدهی path-style و جفت کلید خود پیکربندی کنید. برای مثال: aws --endpoint-url <endpoint> s3 cp ./poster.jpg s3://my-media/posters/. به هیچ کلاینت سفارشی نیازی نیست چون API پروتکل S3 را صحبت میکند.
bucket را به یک اپلیکیشن container متصل کنید
روی یک Container App گزینه Bind Object Storage را انتخاب و bucket را برگزینید. پلتفرم endpoint، region، access key و secret را بهعنوان متغیرهای محیطی (با یک پیشوند اختیاری مانند ASSETS_) تزریق میکند تا کد شما آنها را از محیط بخواند بهجای hardcode کردن اعتبارنامهها در image یا مخزن.
آن را پشت CDN قرار دهید
یک دامنه متصل کنید یا از مسیر edge مربوط به bucket استفاده کنید تا اشیا از cache در مکانهای edge ارائه شوند. هدرهای cache را هنگام آپلود تنظیم کنید، و وقتی یک فایل را زیر همان کلید بازنویسی میکنید از پنل یا cdnctl استفاده کنید تا بینندگان نسخه جدید را دریافت کنند.
محدودیتها را تنظیم و با cdnctl خودکار کنید
یک محدودیت مصرف روی bucket اعمال کنید تا در برابر رشد افسارگسیخته محافظت شوید، و کارهای روتین را با cdnctl اسکریپت کنید تا آپلودهای پشتیبان و پاکسازیها از CI بدون باز کردن پنل اجرا شوند. کلیدها را بهصورت دورهای از همان تب Access Keys بچرخانید.
نمونه سناریوها
یک سایت فروشگاهی هر تصویر محصول و نسخه اصلی آپلودشده را در یک bucket ذخیره میکند، مشتقات را از طریق CDN ارائه میدهد و container های اپلیکیشن را بدونوضعیت نگه میدارد تا deploy ها هرگز به فایلهای کاربر دست نزنند.
یک اپلیکیشن container که به چند replica مقیاس یافته، آپلودهای کاربر را در یک bucket مینویسد، بنابراین هر instance همان فایلها را میخواند و یک restart یا رویداد scale هرگز داده را از دست نمیدهد.
یک کار cron یا CI از یک کلید محدود و cdnctl استفاده میکند تا هر شب dump های فشرده دیتابیس را به یک bucket خصوصی push کند، با یک محدودیت مصرف و پاکسازی نگهداری که هزینه را قابلپیشبینی نگه میدارد.
یک تیم که پیشتر از AWS S3 استفاده میکند، endpoint و کلیدهای SDK خود را به cdn.com.tr تغییر مسیر میدهد، از rclone برای کپی اشیا استفاده میکند و بدون بازنویسی کد ذخیرهسازی منتشر میکند.
پرسشهای پرتکرار
کدام ابزارها و SDK های S3 واقعاً در برابر آن کار میکنند؟
موارد رایج: aws-cli، boto3، AWS SDK for JavaScript، rclone، s3cmd و درایورهای فایلسیستم S3 در Laravel و Symfony. URL از نوع endpoint را از صفحه bucket تنظیم کنید، از آدرسدهی path-style استفاده کنید و access key و secret خود را فراهم کنید. آپلودهای multipart برای اشیای بزرگ پشتیبانی میشوند.
آیا میتوانم فایلهای bucket را مستقیماً از طریق CDN به عموم ارائه دهم؟
بله. bucket یا شیء را عموماً قابلخواندن کنید، یا از مسیر edge مربوط به bucket استفاده کنید، و یک دامنه متصل کنید. آنگاه اشیا در مکانهای edge cache میشوند تا دانلودهای تکراری بهجای زدن هر بار به ذخیرهسازی، از cache ارائه شوند.
وقتی یک فایل را زیر همان کلید بازنویسی میکنم چه اتفاقی میافتد؟
ذخیرهسازی بلافاصله شیء جدید را میگیرد، اما edge ممکن است تا انقضای cache خود همچنان نسخه قبلی را نگه دارد. درست پس از آپلود، یک purge برای آن مسیر از پنل یا با cdnctl اجرا کنید تا بینندگان فایل تازه را بگیرند.
اگر یک access key نشت کند چه کار کنم؟
آن جفت کلید را از تب Access Keys باطل و یک جفت جدید تولید کنید. چون باید کلیدها را بهازای هر bucket یا هر اپلیکیشن محدود کنید، باطل کردن یک جفت سرویسهای دیگر شما را مختل نمیکند. binding یا secret store خود را با secret جدید بهروزرسانی کنید.
آیا باید اعتبارنامهها را در image از نوع container خود hardcode کنم؟
خیر، و نباید. bucket را به Container App، bind کنید و endpoint، region، access key و secret بهعنوان متغیرهای محیطی، بهصورت اختیاری زیر یک پیشوند، میرسند. کد شما آنها را در زمان اجرا میخواند، بنابراین secret ها بیرون از image و مخزن میمانند.
چگونه از رشد بیحد ذخیرهسازی جلوگیری کنم؟
یک محدودیت مصرف روی bucket تنظیم کنید تا بدون توجه بزرگ نشود، و برای bucket های پشتیبان یک پاکسازی نگهداری را با cdnctl اسکریپت کنید تا dump های قدیمی طبق یک زمانبندی هرس شوند. پنل مصرف جاری هر bucket را نشان میدهد تا بتوانید آن را پیگیری کنید.